1 /* 2 Copyright (c) 2019-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #ifndef __TBB_detail__node_handle_H 18 #define __TBB_detail__node_handle_H 19 20 #include "_allocator_traits.h" 21 #include "_assert.h" 22 23 namespace tbb { 24 namespace detail { 25 namespace d1 { 26 27 // A structure to access private node handle methods in internal TBB classes 28 // Regular friend declaration is not convenient because classes which use node handle 29 // can be placed in the different versioning namespaces. 30 struct node_handle_accessor { 31 template <typename NodeHandleType> 32 static typename NodeHandleType::node* get_node_ptr( NodeHandleType& nh ) { 33 return nh.get_node_ptr(); 34 } 35 36 template <typename NodeHandleType> 37 static NodeHandleType construct( typename NodeHandleType::node* node_ptr ) { 38 return NodeHandleType{node_ptr}; 39 } 40 41 template <typename NodeHandleType> 42 static void deactivate( NodeHandleType& nh ) { 43 nh.deactivate(); 44 } 45 }; // struct node_handle_accessor 46 47 template<typename Value, typename Node, typename Allocator> 48 class node_handle_base { 49 public: 50 using allocator_type = Allocator; 51 protected: 52 using node = Node; 53 using allocator_traits_type = tbb::detail::allocator_traits<allocator_type>; 54 public: 55 56 node_handle_base() : my_node(nullptr), my_allocator() {} 57 node_handle_base(node_handle_base&& nh) : my_node(nh.my_node), 58 my_allocator(std::move(nh.my_allocator)) { 59 nh.my_node = nullptr; 60 } 61 62 __TBB_nodiscard bool empty() const { return my_node == nullptr; } 63 explicit operator bool() const { return my_node != nullptr; } 64 65 ~node_handle_base() { internal_destroy(); } 66 67 node_handle_base& operator=( node_handle_base&& nh ) { 68 internal_destroy(); 69 my_node = nh.my_node; 70 move_assign_allocators(my_allocator, nh.my_allocator); 71 nh.deactivate(); 72 return *this; 73 } 74 75 void swap( node_handle_base& nh ) { 76 using std::swap; 77 swap(my_node, nh.my_node); 78 swap_allocators(my_allocator, nh.my_allocator); 79 } 80 81 allocator_type get_allocator() const { 82 return my_allocator; 83 } 84 85 protected: 86 node_handle_base( node* n ) : my_node(n) {} 87 88 void internal_destroy() { 89 if(my_node != nullptr) { 90 allocator_traits_type::destroy(my_allocator, my_node->storage()); 91 typename allocator_traits_type::template rebind_alloc<node> node_allocator(my_allocator); 92 node_allocator.deallocate(my_node, 1); 93 } 94 } 95 96 node* get_node_ptr() { return my_node; } 97 98 void deactivate() { my_node = nullptr; } 99 100 node* my_node; 101 allocator_type my_allocator; 102 }; 103 104 // node handle for maps 105 template<typename Key, typename Value, typename Node, typename Allocator> 106 class node_handle : public node_handle_base<Value, Node, Allocator> { 107 using base_type = node_handle_base<Value, Node, Allocator>; 108 public: 109 using key_type = Key; 110 using mapped_type = typename Value::second_type; 111 using allocator_type = typename base_type::allocator_type; 112 113 node_handle() = default; 114 115 key_type& key() const { 116 __TBB_ASSERT(!this->empty(), "Cannot get key from the empty node_type object"); 117 return *const_cast<key_type*>(&(this->my_node->value().first)); 118 } 119 120 mapped_type& mapped() const { 121 __TBB_ASSERT(!this->empty(), "Cannot get mapped value from the empty node_type object"); 122 return this->my_node->value().second; 123 } 124 125 private: 126 friend struct node_handle_accessor; 127 128 node_handle( typename base_type::node* n ) : base_type(n) {} 129 }; // class node_handle 130 131 // node handle for sets 132 template<typename Key, typename Node, typename Allocator> 133 class node_handle<Key, Key, Node, Allocator> : public node_handle_base<Key, Node, Allocator> { 134 using base_type = node_handle_base<Key, Node, Allocator>; 135 public: 136 using value_type = Key; 137 using allocator_type = typename base_type::allocator_type; 138 139 node_handle() = default; 140 141 value_type& value() const { 142 __TBB_ASSERT(!this->empty(), "Cannot get value from the empty node_type object"); 143 return *const_cast<value_type*>(&(this->my_node->value())); 144 } 145 146 private: 147 friend struct node_handle_accessor; 148 149 node_handle( typename base_type::node* n ) : base_type(n) {} 150 }; // class node_handle 151 152 template <typename Key, typename Value, typename Node, typename Allocator> 153 void swap( node_handle<Key, Value, Node, Allocator>& lhs, 154 node_handle<Key, Value, Node, Allocator>& rhs ) { 155 return lhs.swap(rhs); 156 } 157 158 } // namespace d1 159 } // namespace detail 160 } // namespace tbb 161 162 #endif // __TBB_detail__node_handle_H 163