17 #ifndef __TBB_concurrent_set_H 18 #define __TBB_concurrent_set_H 20 #define __TBB_concurrent_set_H_include_area 23 #if !TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 24 #error Set TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS to include concurrent_set.h 30 #if __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT 35 namespace interface10 {
38 template<
typename Key,
typename KeyCompare,
typename RandomGenerator,
size_t MAX_LEVELS,
typename Allocator,
bool AllowMultimapping>
41 static constexpr
size_t MAX_LEVEL = MAX_LEVELS;
42 using random_level_generator_type = RandomGenerator;
44 using value_type = key_type;
45 using compare_type = KeyCompare;
46 using value_compare = compare_type;
47 using reference = value_type & ;
48 using const_reference =
const value_type&;
49 using allocator_type = Allocator;
53 static const bool allow_multimapping = AllowMultimapping;
55 static const key_type& get_key(const_reference val) {
59 static value_compare value_comp(compare_type comp) {
return comp; }
62 template <
typename Key,
typename Comp,
typename Allocator>
63 class concurrent_multiset;
65 template <
typename Key,
typename Comp = std::less<Key>,
typename Allocator = tbb_allocator<Key>>
67 :
public internal::concurrent_skip_list<set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator, false>> {
68 using traits_type = set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator,
false>;
69 using base_type = internal::concurrent_skip_list<traits_type>;
73 using base_type::allow_multimapping;
76 using value_type =
typename traits_type::value_type;
77 using size_type =
typename base_type::size_type;
78 using difference_type =
typename base_type::difference_type;
79 using key_compare = Comp;
80 using value_compare =
typename base_type::value_compare;
81 using allocator_type = Allocator;
83 using reference =
typename base_type::reference;
84 using const_reference =
typename base_type::const_reference;
85 using pointer =
typename base_type::pointer;
86 using const_pointer =
typename base_type::pointer;
88 using iterator =
typename base_type::iterator;
89 using const_iterator =
typename base_type::const_iterator;
90 using reverse_iterator =
typename base_type::reverse_iterator;
91 using const_reverse_iterator =
typename base_type::const_reverse_iterator;
93 using node_type =
typename base_type::node_type;
95 using base_type::insert;
97 concurrent_set() =
default;
99 explicit concurrent_set(
const key_compare& comp,
const allocator_type& alloc = allocator_type()) : base_type(comp, alloc) {}
101 explicit concurrent_set(
const allocator_type& alloc) : base_type(key_compare(), alloc) {}
103 template<
class InputIt >
104 concurrent_set(InputIt
first, InputIt
last,
const key_compare& comp = Comp(),
const allocator_type& alloc = allocator_type())
107 template<
class InputIt >
108 concurrent_set(InputIt
first, InputIt
last,
const allocator_type& alloc) : base_type(
first,
last, key_compare(), alloc) {}
111 concurrent_set(
const concurrent_set&) =
default;
113 concurrent_set(
const concurrent_set& other,
const allocator_type& alloc) : base_type(other, alloc) {}
115 concurrent_set(concurrent_set&&) =
default;
117 concurrent_set(concurrent_set&& other,
const allocator_type& alloc) : base_type(
std::move(other), alloc) {}
119 concurrent_set(std::initializer_list<value_type> init,
const key_compare& comp = Comp(),
const allocator_type& alloc = allocator_type())
120 : base_type(comp, alloc) {
124 concurrent_set(std::initializer_list<value_type> init,
const allocator_type& alloc)
125 : base_type(key_compare(), alloc) {
129 concurrent_set& operator=(
const concurrent_set& other) {
130 return static_cast<concurrent_set&>(base_type::operator=(other));
133 concurrent_set& operator=(concurrent_set&& other) {
134 return static_cast<concurrent_set&>(base_type::operator=(
std::move(other)));
137 template<
typename C2>
138 void merge(concurrent_set<key_type, C2, Allocator>& source) {
139 this->internal_merge(source);
142 template<
typename C2>
143 void merge(concurrent_set<key_type, C2, Allocator>&& source) {
147 template<
typename C2>
148 void merge(concurrent_multiset<key_type, C2, Allocator>& source) {
149 this->internal_merge(source);
152 template<
typename C2>
153 void merge(concurrent_multiset<key_type, C2, Allocator>&& source) {
158 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 164 template<
template<
typename...>
typename Set,
typename Key,
typename... Args>
165 using c_set_t = Set<Key,
166 std::conditional_t< (
sizeof...(Args) > 0) && !is_allocator_v<pack_element_t<0, Args...> >,
167 pack_element_t<0, Args...>, std::less<Key> >,
168 std::conditional_t< (
sizeof...(Args) > 0) && is_allocator_v<pack_element_t<
sizeof...(Args)-1, Args...> >,
169 pack_element_t<
sizeof...(Args)-1, Args...>, tbb_allocator<Key> > >;
172 template<
typename It,
typename... Args>
173 concurrent_set(It, It, Args...)
174 -> internal::c_set_t<concurrent_set, internal::iterator_value_t<It>, Args...>;
176 template<
typename Key,
typename... Args>
177 concurrent_set(std::initializer_list<Key>, Args...)
178 -> internal::c_set_t<concurrent_set, Key, Args...>;
180 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 182 template <
typename Key,
typename Comp = std::less<Key>,
typename Allocator = tbb_allocator<Key>>
183 class concurrent_multiset
184 :
public internal::concurrent_skip_list<set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator, true>> {
185 using traits_type = set_traits<Key, Comp, internal::concurrent_geometric_level_generator<64>, 64, Allocator,
true>;
186 using base_type = internal::concurrent_skip_list<traits_type>;
187 #if __TBB_EXTRA_DEBUG 190 using base_type::allow_multimapping;
192 using key_type = Key;
193 using value_type =
typename traits_type::value_type;
194 using size_type =
typename base_type::size_type;
195 using difference_type =
typename base_type::difference_type;
196 using key_compare = Comp;
197 using value_compare =
typename base_type::value_compare;
200 using reference =
typename base_type::reference;
201 using const_reference =
typename base_type::const_reference;
202 using pointer =
typename base_type::pointer;
203 using const_pointer =
typename base_type::pointer;
205 using iterator =
typename base_type::iterator;
206 using const_iterator =
typename base_type::const_iterator;
207 using reverse_iterator =
typename base_type::reverse_iterator;
208 using const_reverse_iterator =
typename base_type::const_reverse_iterator;
210 using node_type =
typename base_type::node_type;
212 using base_type::insert;
214 concurrent_multiset() =
default;
218 explicit concurrent_multiset(
const allocator_type& alloc) : base_type(key_compare(), alloc) {}
220 template<
class InputIt >
222 : base_type(comp, alloc) {
226 template<
class InputIt >
227 concurrent_multiset(InputIt
first, InputIt
last,
const allocator_type& alloc) : base_type(key_compare(), alloc) {
232 concurrent_multiset(
const concurrent_multiset&) =
default;
234 concurrent_multiset(
const concurrent_multiset& other,
const allocator_type& alloc) : base_type(other, alloc) {}
236 concurrent_multiset(concurrent_multiset&&) =
default;
238 concurrent_multiset(concurrent_multiset&& other,
const allocator_type& alloc) : base_type(
std::move(other), alloc) {}
240 concurrent_multiset(std::initializer_list<value_type> init,
const key_compare& comp = Comp(),
const allocator_type& alloc =
allocator_type())
241 : base_type(comp, alloc) {
245 concurrent_multiset(std::initializer_list<value_type> init,
const allocator_type& alloc)
246 : base_type(key_compare(), alloc) {
250 concurrent_multiset& operator=(
const concurrent_multiset& other) {
251 return static_cast<concurrent_multiset&>(base_type::operator=(other));
254 concurrent_multiset& operator=(concurrent_multiset&& other) {
255 return static_cast<concurrent_multiset&>(base_type::operator=(
std::move(other)));
258 template<
typename C2>
259 void merge(concurrent_set<key_type, C2, Allocator>& source) {
260 this->internal_merge(source);
263 template<
typename C2>
264 void merge(concurrent_set<key_type, C2, Allocator>&& source) {
268 template<
typename C2>
269 void merge(concurrent_multiset<key_type, C2, Allocator>& source) {
270 this->internal_merge(source);
273 template<
typename C2>
274 void merge(concurrent_multiset<key_type, C2, Allocator>&& source) {
279 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 282 template<
typename It,
typename... Args>
283 concurrent_multiset(It, It, Args...)
284 -> internal::c_set_t<concurrent_multiset, internal::iterator_value_t<It>, Args...>;
286 template<
typename Key,
typename... Args>
287 concurrent_multiset(std::initializer_list<Key>, Args...)
288 -> internal::c_set_t<concurrent_multiset, Key, Args...>;
290 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 294 using interface10::concurrent_set;
295 using interface10::concurrent_multiset;
299 #endif // __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT 302 #undef __TBB_concurrent_set_H_include_area 304 #endif // __TBB_concurrent_set_H A lock that occupies a single byte.
auto last(Container &c) -> decltype(begin(c))
auto first(Container &c) -> decltype(begin(c))
Class for determining type of std::allocator<T>::value_type.
Identifiers declared inside namespace internal should never be used directly by client code.
void move(tbb_thread &t1, tbb_thread &t2)