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>
get_node_ptrnode_handle_accessor32     static typename NodeHandleType::node* get_node_ptr( NodeHandleType& nh ) {
33         return nh.get_node_ptr();
34     }
35 
36     template <typename NodeHandleType>
constructnode_handle_accessor37     static NodeHandleType construct( typename NodeHandleType::node* node_ptr ) {
38         return NodeHandleType{node_ptr};
39     }
40 
41     template <typename NodeHandleType>
deactivatenode_handle_accessor42     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 
node_handle_base()56     node_handle_base() : my_node(nullptr), my_allocator() {}
node_handle_base(node_handle_base && nh)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 
empty()62     __TBB_nodiscard bool empty() const { return my_node == nullptr; }
63     explicit operator bool() const { return my_node != nullptr; }
64 
~node_handle_base()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 
swap(node_handle_base & nh)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 
get_allocator()81     allocator_type get_allocator() const {
82         return my_allocator;
83     }
84 
85 protected:
node_handle_base(node * n)86     node_handle_base( node* n ) : my_node(n) {}
87 
internal_destroy()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 
get_node_ptr()96     node* get_node_ptr() { return my_node; }
97 
deactivate()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 
key()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 
mapped()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 
node_handle(typename base_type::node * n)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 
value()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 
node_handle(typename base_type::node * n)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>
swap(node_handle<Key,Value,Node,Allocator> & lhs,node_handle<Key,Value,Node,Allocator> & rhs)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