/* Copyright (c) 2019-2020 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef __TBB_node_handle_H #define __TBB_node_handle_H #include "_allocator_traits.h" #include "../tbb_config.h" namespace tbb { // This classes must be declared here for correct friendly relationship // TODO: Consider creation some internal class to access node_handle private fields without any friendly classes namespace interface5 { namespace internal { template class split_ordered_list; template class concurrent_unordered_base; } } namespace interface10{ namespace internal { template class concurrent_skip_list; } } namespace internal { template class node_handle_base { public: typedef Allocator allocator_type; protected: typedef Node node; typedef tbb::internal::allocator_traits traits_type; public: node_handle_base() : my_node(NULL), my_allocator() {} node_handle_base(node_handle_base&& nh) : my_node(nh.my_node), my_allocator(std::move(nh.my_allocator)) { nh.my_node = NULL; } bool empty() const { return my_node == NULL; } explicit operator bool() const { return my_node != NULL; } ~node_handle_base() { internal_destroy(); } node_handle_base& operator=(node_handle_base&& nh) { internal_destroy(); my_node = nh.my_node; typedef typename traits_type::propagate_on_container_move_assignment pocma_type; tbb::internal::allocator_move_assignment(my_allocator, nh.my_allocator, pocma_type()); nh.deactivate(); return *this; } void swap(node_handle_base& nh) { std::swap(my_node, nh.my_node); typedef typename traits_type::propagate_on_container_swap pocs_type; tbb::internal::allocator_swap(my_allocator, nh.my_allocator, pocs_type()); } allocator_type get_allocator() const { return my_allocator; } protected: node_handle_base(node* n) : my_node(n) {} void internal_destroy() { if(my_node) { traits_type::destroy(my_allocator, my_node->storage()); typename tbb::internal::allocator_rebind::type node_allocator; node_allocator.deallocate(my_node, 1); } } void deactivate() { my_node = NULL; } node* my_node; allocator_type my_allocator; }; // node handle for maps template class node_handle : public node_handle_base { typedef node_handle_base base_type; public: typedef Key key_type; typedef typename Value::second_type mapped_type; typedef typename base_type::allocator_type allocator_type; node_handle() : base_type() {} key_type& key() const { __TBB_ASSERT(!this->empty(), "Cannot get key from the empty node_type object"); return *const_cast(&(this->my_node->value().first)); } mapped_type& mapped() const { __TBB_ASSERT(!this->empty(), "Cannot get mapped value from the empty node_type object"); return this->my_node->value().second; } private: template friend class tbb::interface5::internal::split_ordered_list; template friend class tbb::interface5::internal::concurrent_unordered_base; template friend class tbb::interface10::internal::concurrent_skip_list; node_handle(typename base_type::node* n) : base_type(n) {} }; // node handle for sets template class node_handle : public node_handle_base { typedef node_handle_base base_type; public: typedef Key value_type; typedef typename base_type::allocator_type allocator_type; node_handle() : base_type() {} value_type& value() const { __TBB_ASSERT(!this->empty(), "Cannot get value from the empty node_type object"); return *const_cast(&(this->my_node->value())); } private: template friend class tbb::interface5::internal::split_ordered_list; template friend class tbb::interface5::internal::concurrent_unordered_base; template friend class tbb::interface10::internal::concurrent_skip_list; node_handle(typename base_type::node* n) : base_type(n) {} }; }// namespace internal }// namespace tbb #endif /*__TBB_node_handle_H*/