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