xref: /oneTBB/include/oneapi/tbb/concurrent_set.h (revision 2713d41e)
149e08aacStbbdev /*
2b15aabb3Stbbdev     Copyright (c) 2019-2021 Intel Corporation
349e08aacStbbdev 
449e08aacStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
549e08aacStbbdev     you may not use this file except in compliance with the License.
649e08aacStbbdev     You may obtain a copy of the License at
749e08aacStbbdev 
849e08aacStbbdev         http://www.apache.org/licenses/LICENSE-2.0
949e08aacStbbdev 
1049e08aacStbbdev     Unless required by applicable law or agreed to in writing, software
1149e08aacStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1249e08aacStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349e08aacStbbdev     See the License for the specific language governing permissions and
1449e08aacStbbdev     limitations under the License.
1549e08aacStbbdev */
1649e08aacStbbdev 
1749e08aacStbbdev #ifndef __TBB_concurrent_set_H
1849e08aacStbbdev #define __TBB_concurrent_set_H
1949e08aacStbbdev 
2049e08aacStbbdev #include "detail/_namespace_injection.h"
2149e08aacStbbdev #include "detail/_concurrent_skip_list.h"
2249e08aacStbbdev #include "tbb_allocator.h"
2349e08aacStbbdev #include <functional>
2449e08aacStbbdev #include <utility>
2549e08aacStbbdev 
2649e08aacStbbdev namespace tbb {
2749e08aacStbbdev namespace detail {
28d8251013SAnton Potapov namespace d2 {
2949e08aacStbbdev 
3049e08aacStbbdev template<typename Key, typename KeyCompare, typename RandomGenerator, typename Allocator, bool AllowMultimapping>
3149e08aacStbbdev struct set_traits {
3249e08aacStbbdev     static constexpr std::size_t max_level = RandomGenerator::max_level;
3349e08aacStbbdev     using random_level_generator_type = RandomGenerator;
3449e08aacStbbdev     using key_type = Key;
3549e08aacStbbdev     using value_type = key_type;
3649e08aacStbbdev     using compare_type = KeyCompare;
3749e08aacStbbdev     using value_compare = compare_type;
3849e08aacStbbdev     using reference = value_type&;
3949e08aacStbbdev     using const_reference = const value_type&;
4049e08aacStbbdev     using allocator_type = Allocator;
4149e08aacStbbdev 
4249e08aacStbbdev     static constexpr bool allow_multimapping = AllowMultimapping;
4349e08aacStbbdev 
get_keyset_traits4449e08aacStbbdev     static const key_type& get_key(const_reference val) {
4549e08aacStbbdev         return val;
4649e08aacStbbdev     }
4749e08aacStbbdev 
value_compset_traits4849e08aacStbbdev     static value_compare value_comp(compare_type comp) { return comp; }
4949e08aacStbbdev }; // struct set_traits
5049e08aacStbbdev 
5149e08aacStbbdev template <typename Key, typename Compare, typename Allocator>
5249e08aacStbbdev class concurrent_multiset;
5349e08aacStbbdev 
5449e08aacStbbdev template <typename Key, typename Compare = std::less<Key>, typename Allocator = tbb::tbb_allocator<Key>>
5549e08aacStbbdev class concurrent_set : public concurrent_skip_list<set_traits<Key, Compare, concurrent_geometric_level_generator<32>, Allocator, false>> {
5649e08aacStbbdev     using base_type = concurrent_skip_list<set_traits<Key, Compare, concurrent_geometric_level_generator<32>, Allocator, false>>;
5749e08aacStbbdev public:
5849e08aacStbbdev     using key_type = Key;
5949e08aacStbbdev     using value_type = typename base_type::value_type;
6049e08aacStbbdev     using size_type = typename base_type::size_type;
6149e08aacStbbdev     using difference_type = typename base_type::difference_type;
6249e08aacStbbdev     using key_compare = Compare;
6349e08aacStbbdev     using value_compare = typename base_type::value_compare;
6449e08aacStbbdev     using allocator_type = Allocator;
6549e08aacStbbdev 
6649e08aacStbbdev     using reference = typename base_type::reference;
6749e08aacStbbdev     using const_reference = typename base_type::const_reference;
6849e08aacStbbdev     using pointer = typename base_type::pointer;
6949e08aacStbbdev     using const_pointer = typename base_type::const_pointer;
7049e08aacStbbdev 
7149e08aacStbbdev     using iterator = typename base_type::iterator;
7249e08aacStbbdev     using const_iterator = typename base_type::const_iterator;
7349e08aacStbbdev 
7449e08aacStbbdev     using node_type = typename base_type::node_type;
7549e08aacStbbdev 
7649e08aacStbbdev     // Include constructors of base_type
7749e08aacStbbdev     using base_type::base_type;
7849e08aacStbbdev 
79d86ed7fbStbbdev     // Required for implicit deduction guides
80d86ed7fbStbbdev     concurrent_set() = default;
81d86ed7fbStbbdev     concurrent_set( const concurrent_set& ) = default;
concurrent_set(const concurrent_set & other,const allocator_type & alloc)82d86ed7fbStbbdev     concurrent_set( const concurrent_set& other, const allocator_type& alloc ) : base_type(other, alloc) {}
83d86ed7fbStbbdev     concurrent_set( concurrent_set&& ) = default;
concurrent_set(concurrent_set && other,const allocator_type & alloc)84d86ed7fbStbbdev     concurrent_set( concurrent_set&& other, const allocator_type& alloc ) : base_type(std::move(other), alloc) {}
85d86ed7fbStbbdev     // Required to respect the rule of 5
86d86ed7fbStbbdev     concurrent_set& operator=( const concurrent_set& ) = default;
87d86ed7fbStbbdev     concurrent_set& operator=( concurrent_set&& ) = default;
88d86ed7fbStbbdev 
89*2713d41eSIlya Isaev     concurrent_set& operator=( std::initializer_list<value_type> il ) {
90*2713d41eSIlya Isaev         base_type::operator= (il);
91*2713d41eSIlya Isaev         return *this;
92*2713d41eSIlya Isaev     }
93*2713d41eSIlya Isaev 
9449e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_set<key_type,OtherCompare,Allocator> & source)9549e08aacStbbdev     void merge(concurrent_set<key_type, OtherCompare, Allocator>& source) {
9649e08aacStbbdev         this->internal_merge(source);
9749e08aacStbbdev     }
9849e08aacStbbdev 
9949e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_set<key_type,OtherCompare,Allocator> && source)10049e08aacStbbdev     void merge(concurrent_set<key_type, OtherCompare, Allocator>&& source) {
10149e08aacStbbdev         this->internal_merge(std::move(source));
10249e08aacStbbdev     }
10349e08aacStbbdev 
10449e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_multiset<key_type,OtherCompare,Allocator> & source)10549e08aacStbbdev     void merge(concurrent_multiset<key_type, OtherCompare, Allocator>& source) {
10649e08aacStbbdev         this->internal_merge(source);
10749e08aacStbbdev     }
10849e08aacStbbdev 
10949e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_multiset<key_type,OtherCompare,Allocator> && source)11049e08aacStbbdev     void merge(concurrent_multiset<key_type, OtherCompare, Allocator>&& source) {
11149e08aacStbbdev         this->internal_merge(std::move(source));
11249e08aacStbbdev     }
11349e08aacStbbdev }; // class concurrent_set
11449e08aacStbbdev 
11549e08aacStbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
11649e08aacStbbdev 
117d86ed7fbStbbdev template <typename It,
118d86ed7fbStbbdev           typename Comp = std::less<iterator_value_t<It>>,
119d86ed7fbStbbdev           typename Alloc = tbb::tbb_allocator<iterator_value_t<It>>,
120d86ed7fbStbbdev           typename = std::enable_if_t<is_input_iterator_v<It>>,
121d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>,
122d86ed7fbStbbdev           typename = std::enable_if_t<!is_allocator_v<Comp>>>
123d86ed7fbStbbdev concurrent_set( It, It, Comp = Comp(), Alloc = Alloc() )
124d86ed7fbStbbdev -> concurrent_set<iterator_value_t<It>, Comp, Alloc>;
12549e08aacStbbdev 
126d86ed7fbStbbdev template <typename Key,
127d86ed7fbStbbdev           typename Comp = std::less<Key>,
128d86ed7fbStbbdev           typename Alloc = tbb::tbb_allocator<Key>,
129d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>,
130d86ed7fbStbbdev           typename = std::enable_if_t<!is_allocator_v<Comp>>>
131d86ed7fbStbbdev concurrent_set( std::initializer_list<Key>, Comp = Comp(), Alloc = Alloc() )
132d86ed7fbStbbdev -> concurrent_set<Key, Comp, Alloc>;
13349e08aacStbbdev 
134d86ed7fbStbbdev template <typename It, typename Alloc,
135d86ed7fbStbbdev           typename = std::enable_if_t<is_input_iterator_v<It>>,
136d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>>
137d86ed7fbStbbdev concurrent_set( It, It, Alloc )
138d86ed7fbStbbdev -> concurrent_set<iterator_value_t<It>,
139d86ed7fbStbbdev                   std::less<iterator_value_t<It>>, Alloc>;
140d86ed7fbStbbdev 
141d86ed7fbStbbdev template <typename Key, typename Alloc,
142d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>>
143d86ed7fbStbbdev concurrent_set( std::initializer_list<Key>, Alloc )
144d86ed7fbStbbdev -> concurrent_set<Key, std::less<Key>, Alloc>;
14549e08aacStbbdev 
14649e08aacStbbdev #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
14749e08aacStbbdev 
14849e08aacStbbdev template <typename Key, typename Compare, typename Allocator>
swap(concurrent_set<Key,Compare,Allocator> & lhs,concurrent_set<Key,Compare,Allocator> & rhs)14949e08aacStbbdev void swap( concurrent_set<Key, Compare, Allocator>& lhs,
15049e08aacStbbdev            concurrent_set<Key, Compare, Allocator>& rhs )
15149e08aacStbbdev {
15249e08aacStbbdev     lhs.swap(rhs);
15349e08aacStbbdev }
15449e08aacStbbdev 
15549e08aacStbbdev template <typename Key, typename Compare = std::less<Key>, typename Allocator = tbb::tbb_allocator<Key>>
15649e08aacStbbdev class concurrent_multiset : public concurrent_skip_list<set_traits<Key, Compare, concurrent_geometric_level_generator<32>, Allocator, true>> {
15749e08aacStbbdev     using base_type = concurrent_skip_list<set_traits<Key, Compare, concurrent_geometric_level_generator<32>, Allocator, true>>;
15849e08aacStbbdev public:
15949e08aacStbbdev     using key_type = Key;
16049e08aacStbbdev     using value_type = typename base_type::value_type;
16149e08aacStbbdev     using size_type = typename base_type::size_type;
16249e08aacStbbdev     using difference_type = typename base_type::difference_type;
16349e08aacStbbdev     using key_compare = Compare;
16449e08aacStbbdev     using value_compare = typename base_type::value_compare;
16549e08aacStbbdev     using allocator_type = Allocator;
16649e08aacStbbdev 
16749e08aacStbbdev     using reference = typename base_type::reference;
16849e08aacStbbdev     using const_reference = typename base_type::const_reference;
16949e08aacStbbdev     using pointer = typename base_type::pointer;
17049e08aacStbbdev     using const_pointer = typename base_type::const_pointer;
17149e08aacStbbdev 
17249e08aacStbbdev     using iterator = typename base_type::iterator;
17349e08aacStbbdev     using const_iterator = typename base_type::const_iterator;
17449e08aacStbbdev 
17549e08aacStbbdev     using node_type = typename base_type::node_type;
17649e08aacStbbdev 
17749e08aacStbbdev     // Include constructors of base_type;
17849e08aacStbbdev     using base_type::base_type;
17949e08aacStbbdev 
180d86ed7fbStbbdev     // Required for implicit deduction guides
181d86ed7fbStbbdev     concurrent_multiset() = default;
182d86ed7fbStbbdev     concurrent_multiset( const concurrent_multiset& ) = default;
concurrent_multiset(const concurrent_multiset & other,const allocator_type & alloc)183d86ed7fbStbbdev     concurrent_multiset( const concurrent_multiset& other, const allocator_type& alloc ) : base_type(other, alloc) {}
184d86ed7fbStbbdev     concurrent_multiset( concurrent_multiset&& ) = default;
concurrent_multiset(concurrent_multiset && other,const allocator_type & alloc)185d86ed7fbStbbdev     concurrent_multiset( concurrent_multiset&& other, const allocator_type& alloc ) : base_type(std::move(other), alloc) {}
186d86ed7fbStbbdev     // Required to respect the rule of 5
187d86ed7fbStbbdev     concurrent_multiset& operator=( const concurrent_multiset& ) = default;
188d86ed7fbStbbdev     concurrent_multiset& operator=( concurrent_multiset&& ) = default;
189d86ed7fbStbbdev 
190*2713d41eSIlya Isaev     concurrent_multiset& operator=( std::initializer_list<value_type> il ) {
191*2713d41eSIlya Isaev         base_type::operator= (il);
192*2713d41eSIlya Isaev         return *this;
193*2713d41eSIlya Isaev     }
194*2713d41eSIlya Isaev 
19549e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_set<key_type,OtherCompare,Allocator> & source)19649e08aacStbbdev     void merge(concurrent_set<key_type, OtherCompare, Allocator>& source) {
19749e08aacStbbdev         this->internal_merge(source);
19849e08aacStbbdev     }
19949e08aacStbbdev 
20049e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_set<key_type,OtherCompare,Allocator> && source)20149e08aacStbbdev     void merge(concurrent_set<key_type, OtherCompare, Allocator>&& source) {
20249e08aacStbbdev         this->internal_merge(std::move(source));
20349e08aacStbbdev     }
20449e08aacStbbdev 
20549e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_multiset<key_type,OtherCompare,Allocator> & source)20649e08aacStbbdev     void merge(concurrent_multiset<key_type, OtherCompare, Allocator>& source) {
20749e08aacStbbdev         this->internal_merge(source);
20849e08aacStbbdev     }
20949e08aacStbbdev 
21049e08aacStbbdev     template<typename OtherCompare>
merge(concurrent_multiset<key_type,OtherCompare,Allocator> && source)21149e08aacStbbdev     void merge(concurrent_multiset<key_type, OtherCompare, Allocator>&& source) {
21249e08aacStbbdev         this->internal_merge(std::move(source));
21349e08aacStbbdev     }
21449e08aacStbbdev }; // class concurrent_multiset
21549e08aacStbbdev 
21649e08aacStbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
21749e08aacStbbdev 
218d86ed7fbStbbdev template <typename It,
219d86ed7fbStbbdev           typename Comp = std::less<iterator_value_t<It>>,
220d86ed7fbStbbdev           typename Alloc = tbb::tbb_allocator<iterator_value_t<It>>,
221d86ed7fbStbbdev           typename = std::enable_if_t<is_input_iterator_v<It>>,
222d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>,
223d86ed7fbStbbdev           typename = std::enable_if_t<!is_allocator_v<Comp>>>
224d86ed7fbStbbdev concurrent_multiset( It, It, Comp = Comp(), Alloc = Alloc() )
225d86ed7fbStbbdev -> concurrent_multiset<iterator_value_t<It>, Comp, Alloc>;
22649e08aacStbbdev 
227d86ed7fbStbbdev template <typename Key,
228d86ed7fbStbbdev           typename Comp = std::less<Key>,
229d86ed7fbStbbdev           typename Alloc = tbb::tbb_allocator<Key>,
230d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>,
231d86ed7fbStbbdev           typename = std::enable_if_t<!is_allocator_v<Comp>>>
232d86ed7fbStbbdev concurrent_multiset( std::initializer_list<Key>, Comp = Comp(), Alloc = Alloc() )
233d86ed7fbStbbdev -> concurrent_multiset<Key, Comp, Alloc>;
234d86ed7fbStbbdev 
235d86ed7fbStbbdev template <typename It, typename Alloc,
236d86ed7fbStbbdev           typename = std::enable_if_t<is_input_iterator_v<It>>,
237d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>>
238d86ed7fbStbbdev concurrent_multiset( It, It, Alloc )
239d86ed7fbStbbdev -> concurrent_multiset<iterator_value_t<It>, std::less<iterator_value_t<It>>, Alloc>;
240d86ed7fbStbbdev 
241d86ed7fbStbbdev template <typename Key, typename Alloc,
242d86ed7fbStbbdev           typename = std::enable_if_t<is_allocator_v<Alloc>>>
243d86ed7fbStbbdev concurrent_multiset( std::initializer_list<Key>, Alloc )
244d86ed7fbStbbdev -> concurrent_multiset<Key, std::less<Key>, Alloc>;
24549e08aacStbbdev 
24649e08aacStbbdev #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
24749e08aacStbbdev 
24849e08aacStbbdev template <typename Key, typename Compare, typename Allocator>
swap(concurrent_multiset<Key,Compare,Allocator> & lhs,concurrent_multiset<Key,Compare,Allocator> & rhs)24949e08aacStbbdev void swap( concurrent_multiset<Key, Compare, Allocator>& lhs,
25049e08aacStbbdev            concurrent_multiset<Key, Compare, Allocator>& rhs )
25149e08aacStbbdev {
25249e08aacStbbdev     lhs.swap(rhs);
25349e08aacStbbdev }
25449e08aacStbbdev 
255d8251013SAnton Potapov } // namespace d2
25649e08aacStbbdev } // namespace detail
25749e08aacStbbdev 
25849e08aacStbbdev inline namespace v1 {
25949e08aacStbbdev 
260d8251013SAnton Potapov using detail::d2::concurrent_set;
261d8251013SAnton Potapov using detail::d2::concurrent_multiset;
26249e08aacStbbdev using detail::split;
26349e08aacStbbdev 
26449e08aacStbbdev } // inline namespace v1
26549e08aacStbbdev } // namespace tbb
26649e08aacStbbdev 
26749e08aacStbbdev #endif // __TBB_concurrent_set_H
268