17 #ifndef __TBB_concurrent_set_H 18 #define __TBB_concurrent_set_H 20 #if !TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 21 #error Set TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS to include concurrent_set.h 27 #if __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT 32 namespace interface10 {
35 template<
typename Key,
typename KeyCompare,
typename RandomGenerator,
size_t MAX_LEVELS,
typename Allocator,
bool AllowMultimapping>
38 static constexpr
size_t MAX_LEVEL = MAX_LEVELS;
39 using random_level_generator_type = RandomGenerator;
41 using value_type = key_type;
42 using compare_type = KeyCompare;
43 using value_compare = compare_type;
44 using reference = value_type & ;
45 using const_reference =
const value_type&;
46 using allocator_type = Allocator;
50 static const bool allow_multimapping = AllowMultimapping;
52 static const key_type& get_key(const_reference val) {
56 static value_compare value_comp(compare_type comp) {
return comp; }
59 template <
typename Key,
typename Comp,
typename Allocator>
60 class concurrent_multiset;
62 template <
typename Key,
typename Comp = std::less<Key>,
typename Allocator = tbb_allocator<Key>>
64 :
public internal::concurrent_skip_list<set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator, false>> {
65 using traits_type = set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator,
false>;
66 using base_type = internal::concurrent_skip_list<traits_type>;
70 using base_type::allow_multimapping;
73 using value_type =
typename traits_type::value_type;
74 using size_type =
typename base_type::size_type;
75 using difference_type =
typename base_type::difference_type;
76 using key_compare = Comp;
77 using value_compare =
typename base_type::value_compare;
78 using allocator_type = Allocator;
80 using reference =
typename base_type::reference;
81 using const_reference =
typename base_type::const_reference;
82 using pointer =
typename base_type::pointer;
83 using const_pointer =
typename base_type::pointer;
85 using iterator =
typename base_type::iterator;
86 using const_iterator =
typename base_type::const_iterator;
87 using reverse_iterator =
typename base_type::reverse_iterator;
88 using const_reverse_iterator =
typename base_type::const_reverse_iterator;
90 using node_type =
typename base_type::node_type;
92 using base_type::insert;
94 concurrent_set() =
default;
96 explicit concurrent_set(
const key_compare& comp,
const allocator_type& alloc = allocator_type()) : base_type(comp, alloc) {}
98 explicit concurrent_set(
const allocator_type& alloc) : base_type(key_compare(), alloc) {}
100 template<
class InputIt >
101 concurrent_set(InputIt
first, InputIt
last,
const key_compare& comp = Comp(),
const allocator_type& alloc = allocator_type())
102 : base_type(first, last, comp, alloc) {}
104 template<
class InputIt >
105 concurrent_set(InputIt first, InputIt last,
const allocator_type& alloc) : base_type(first, last, key_compare(), alloc) {}
108 concurrent_set(
const concurrent_set&) =
default;
110 concurrent_set(
const concurrent_set& other,
const allocator_type& alloc) : base_type(other, alloc) {}
112 concurrent_set(concurrent_set&&) =
default;
114 concurrent_set(concurrent_set&& other,
const allocator_type& alloc) : base_type(
std::
move(other), alloc) {}
116 concurrent_set(std::initializer_list<value_type> init,
const key_compare& comp = Comp(),
const allocator_type& alloc = allocator_type())
117 : base_type(comp, alloc) {
121 concurrent_set(std::initializer_list<value_type> init,
const allocator_type& alloc)
122 : base_type(key_compare(), alloc) {
126 concurrent_set& operator=(
const concurrent_set& other) {
127 return static_cast<concurrent_set&
>(base_type::operator=(other));
130 concurrent_set& operator=(concurrent_set&& other) {
131 return static_cast<concurrent_set&
>(base_type::operator=(
std::move(other)));
134 template<
typename C2>
135 void merge(concurrent_set<key_type, C2, Allocator>& source) {
136 this->internal_merge(source);
139 template<
typename C2>
140 void merge(concurrent_set<key_type, C2, Allocator>&& source) {
144 template<
typename C2>
145 void merge(concurrent_multiset<key_type, C2, Allocator>& source) {
146 this->internal_merge(source);
149 template<
typename C2>
150 void merge(concurrent_multiset<key_type, C2, Allocator>&& source) {
155 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 161 template<
template<
typename...>
typename Set,
typename Key,
typename... Args>
162 using c_set_t = Set<Key,
163 std::conditional_t< (
sizeof...(Args) > 0) && !is_allocator_v<pack_element_t<0, Args...> >,
164 pack_element_t<0, Args...>, std::less<Key> >,
165 std::conditional_t< (
sizeof...(Args) > 0) && is_allocator_v<pack_element_t<
sizeof...(Args)-1, Args...> >,
166 pack_element_t<
sizeof...(Args)-1, Args...>, tbb_allocator<Key> > >;
169 template<
typename It,
typename... Args>
170 concurrent_set(It, It, Args...)
171 -> internal::c_set_t<concurrent_set, internal::iterator_value_t<It>, Args...>;
173 template<
typename Key,
typename... Args>
174 concurrent_set(std::initializer_list<Key>, Args...)
175 -> internal::c_set_t<concurrent_set, Key, Args...>;
177 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 179 template <
typename Key,
typename Comp = std::less<Key>,
typename Allocator = tbb_allocator<Key>>
180 class concurrent_multiset
181 :
public internal::concurrent_skip_list<set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator, true>> {
182 using traits_type = set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator,
true>;
183 using base_type = internal::concurrent_skip_list<traits_type>;
184 #if __TBB_EXTRA_DEBUG 187 using base_type::allow_multimapping;
189 using key_type = Key;
190 using value_type =
typename traits_type::value_type;
191 using size_type =
typename base_type::size_type;
192 using difference_type =
typename base_type::difference_type;
193 using key_compare = Comp;
194 using value_compare =
typename base_type::value_compare;
197 using reference =
typename base_type::reference;
198 using const_reference =
typename base_type::const_reference;
199 using pointer =
typename base_type::pointer;
200 using const_pointer =
typename base_type::pointer;
202 using iterator =
typename base_type::iterator;
203 using const_iterator =
typename base_type::const_iterator;
204 using reverse_iterator =
typename base_type::reverse_iterator;
205 using const_reverse_iterator =
typename base_type::const_reverse_iterator;
207 using node_type =
typename base_type::node_type;
209 using base_type::insert;
211 concurrent_multiset() =
default;
215 explicit concurrent_multiset(
const allocator_type& alloc) : base_type(key_compare(), alloc) {}
217 template<
class InputIt >
219 : base_type(comp, alloc) {
223 template<
class InputIt >
224 concurrent_multiset(InputIt first, InputIt last,
const allocator_type& alloc) : base_type(key_compare(), alloc) {
229 concurrent_multiset(
const concurrent_multiset&) =
default;
231 concurrent_multiset(
const concurrent_multiset& other,
const allocator_type& alloc) : base_type(other, alloc) {}
233 concurrent_multiset(concurrent_multiset&&) =
default;
235 concurrent_multiset(concurrent_multiset&& other,
const allocator_type& alloc) : base_type(
std::
move(other), alloc) {}
237 concurrent_multiset(std::initializer_list<value_type> init,
const key_compare& comp = Comp(),
const allocator_type& alloc =
allocator_type())
238 : base_type(comp, alloc) {
242 concurrent_multiset(std::initializer_list<value_type> init,
const allocator_type& alloc)
243 : base_type(key_compare(), alloc) {
247 concurrent_multiset& operator=(
const concurrent_multiset& other) {
248 return static_cast<concurrent_multiset&
>(base_type::operator=(other));
251 concurrent_multiset& operator=(concurrent_multiset&& other) {
252 return static_cast<concurrent_multiset&
>(base_type::operator=(
std::move(other)));
255 template<
typename C2>
256 void merge(concurrent_set<key_type, C2, Allocator>& source) {
257 this->internal_merge(source);
260 template<
typename C2>
261 void merge(concurrent_set<key_type, C2, Allocator>&& source) {
265 template<
typename C2>
266 void merge(concurrent_multiset<key_type, C2, Allocator>& source) {
267 this->internal_merge(source);
270 template<
typename C2>
271 void merge(concurrent_multiset<key_type, C2, Allocator>&& source) {
276 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 279 template<
typename It,
typename... Args>
280 concurrent_multiset(It, It, Args...)
281 -> internal::c_set_t<concurrent_multiset, internal::iterator_value_t<It>, Args...>;
283 template<
typename Key,
typename... Args>
284 concurrent_multiset(std::initializer_list<Key>, Args...)
285 -> internal::c_set_t<concurrent_multiset, Key, Args...>;
287 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 291 using interface10::concurrent_set;
292 using interface10::concurrent_multiset;
296 #endif // __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT 297 #endif // __TBB_concurrent_set_H auto last(Container &c) -> decltype(begin(c))
auto first(Container &c) -> decltype(begin(c))
void move(tbb_thread &t1, tbb_thread &t2)
Identifiers declared inside namespace internal should never be used directly by client code...
Class for determining type of std::allocator<T>::value_type.
A lock that occupies a single byte.