2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H
32 #define CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H
34 #include <cds/intrusive/split_list_rcu.h>
35 #include <cds/container/details/make_split_list_set.h>
36 #include <cds/urcu/exempt_ptr.h>
38 namespace cds { namespace container {
41 namespace split_list { namespace details {
50 #ifdef CDSLIB_CONTAINER_DETAILS_MICHAEL_LIST_BASE_H
51 template <typename T, class RawPtr>
52 class make_raw_ptr< T, RawPtr, cds::container::michael_list_tag >
54 typedef RawPtr intrusive_raw_ptr;
55 typedef typename intrusive_raw_ptr::value_type node_type;
58 struct raw_ptr_converter
60 value_type * operator()( node_type * p ) const
62 return p ? &p->m_Value : nullptr;
65 value_type& operator()( node_type& n ) const
70 value_type const& operator()( node_type const& n ) const
76 typedef cds::urcu::raw_ptr_adaptor< value_type, intrusive_raw_ptr, raw_ptr_converter > raw_ptr;
78 static raw_ptr make( intrusive_raw_ptr&& p )
80 return raw_ptr(std::move( p ));
85 #ifdef CDSLIB_CONTAINER_DETAILS_LAZY_LIST_BASE_H
86 template <typename T, typename RawPtr>
87 class make_raw_ptr< T, RawPtr, cds::container::lazy_list_tag >
89 typedef RawPtr node_type_pointer;
93 typedef value_type * raw_ptr;
95 static raw_ptr make( node_type_pointer p )
97 return p ? &p->m_Value : nullptr;
101 }} //namespace split_list::details
104 /// Split-ordered list set (template specialization for \ref cds_urcu_desc "RCU")
105 /** @ingroup cds_nonintrusive_set
106 \anchor cds_nonintrusive_SplitListSet_rcu
108 Hash table implementation based on split-ordered list algorithm discovered by Ori Shalev and Nir Shavit, see
109 - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables"
110 - [2008] Nir Shavit "The Art of Multiprocessor Programming"
112 See \p intrusive::SplitListSet for a brief description of the split-list algorithm.
115 - \p RCU - one of \ref cds_urcu_gc "RCU type"
116 - \p T - type of the value to be stored in the split-list.
117 - \p Traits - type traits, default is \p split_list::traits. Instead of declaring \p split_list::traits -based
118 struct you can apply option-based notation with \p split_list::make_traits metafunction.
122 The class supports a forward iterator (\ref iterator and \ref const_iterator).
123 The iteration is unordered.
125 You may iterate over split-list set items only under RCU lock.
126 Only in this case the iterator is thread-safe since
127 while RCU is locked any set's item cannot be reclaimed.
129 @warning The iterator object cannot be passed between threads
131 \warning Due to concurrent nature of skip-list set it is not guarantee that you can iterate
132 all elements in the set: any concurrent deletion can exclude the element
133 pointed by the iterator from the set, and your iteration can be terminated
134 before end of the set. Therefore, such iteration is more suitable for debugging purposes
136 The iterator class supports the following minimalistic interface:
143 iterator( iterator const& s);
145 value_type * operator ->() const;
146 value_type& operator *() const;
149 iterator& operator ++();
152 iterator& operator = (const iterator& src);
154 bool operator ==(iterator const& i ) const;
155 bool operator !=(iterator const& i ) const;
158 Note, the iterator object returned by \p end(), \p cend() member functions points to \p nullptr and should not be dereferenced.
162 You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list
163 is an original data structure based on an ordered list. Suppose, you want construct split-list set based on \p cds::urcu::general_buffered<> GC
164 and \p LazyList as ordered list implementation. So, you beginning your program with following include:
166 #include <cds/urcu/general_buffered.h>
167 #include <cds/container/lazy_list_rcu.h>
168 #include <cds/container/split_list_set_rcu.h>
170 namespace cc = cds::container;
172 // The data belonged to split-ordered list
174 int nKey; // key field
175 std::string strValue ; // value field
178 The inclusion order is important:
179 - first, include one of \ref cds_urcu_gc "RCU implementation" (<tt>cds/urcu/general_buffered.h</tt> in our case)
180 - second, include file for ordered-list implementation (for this example, <tt>cds/container/lazy_list_rcu.h</tt>),
181 - then, the header for RCU-based split-list set <tt>cds/container/split_list_set_rcu.h</tt>.
183 Now, you should declare traits for split-list set. The main parts of traits are a hash functor for the set and a comparing functor for ordered list.
184 Note that we define several function in \p foo_hash and \p foo_less functors for different argument types since we want call our \p %SplitListSet
185 object by the key of type \p int and by the value of type \p foo.
187 The second attention: instead of using \p %LazyList in \p %SplitListSet traits we use \p cds::contaner::lazy_list_tag tag for the lazy list.
188 The split-list requires significant support from underlying ordered list class and it is not good idea to dive you
189 into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface.
194 size_t operator()( int key ) const { return std::hash( key ) ; }
195 size_t operator()( foo const& item ) const { return std::hash( item.nKey ) ; }
200 bool operator()(int i, foo const& f ) const { return i < f.nKey ; }
201 bool operator()(foo const& f, int i ) const { return f.nKey < i ; }
202 bool operator()(foo const& f1, foo const& f2) const { return f1.nKey < f2.nKey; }
205 // SplitListSet traits
206 struct foo_set_traits: public cc::split_list::traits
208 typedef cc::lazy_list_tag ordered_list ; // what type of ordered list we want to use
209 typedef foo_hash hash ; // hash functor for our data stored in split-list set
211 // Type traits for our LazyList class
212 struct ordered_list_traits: public cc::lazy_list::traits
214 typedef foo_less less ; // use our foo_less as comparator to order list nodes
219 Now you are ready to declare our set class based on \p %SplitListSet:
221 typedef cc::SplitListSet< cds::urcu::gc<cds::urcu::general_buffered<> >, foo, foo_set_traits > foo_set;
224 You may use the modern option-based declaration instead of classic type-traits-based one:
226 typedef cc::SplitListSet<
227 cds::urcu::gc<cds::urcu::general_buffered<> > // RCU type used
228 ,foo // type of data stored
229 ,cc::split_list::make_traits< // metafunction to build split-list traits
230 cc::split_list::ordered_list<cc::lazy_list_tag> // tag for underlying ordered list implementation
231 ,cc::opt::hash< foo_hash > // hash functor
232 ,cc::split_list::ordered_list_traits< // ordered list traits
233 cc::lazy_list::make_traits< // metafunction to build lazy list traits
234 cc::opt::less< foo_less > // less-based compare functor
240 In case of option-based declaration using \p split_list::make_traits metafunction
241 the struct \p foo_set_traits is not required.
243 Now, the set of type \p foo_set is ready to use in your program.
245 Note that in this example we show only mandatory \p traits parts, optional ones is the default and they are inherited
246 from \p container::split_list::traits.
247 There are many other options for deep tuning of the split-list and ordered-list containers.
252 #ifdef CDS_DOXYGEN_INVOKED
253 class Traits = split_list::traits
258 class SplitListSet< cds::urcu::gc< RCU >, T, Traits >:
259 #ifdef CDS_DOXYGEN_INVOKED
260 protected intrusive::SplitListSet< cds::urcu::gc< RCU >, T, typename Traits::ordered_list, Traits >
262 protected details::make_split_list_set< cds::urcu::gc< RCU >, T, typename Traits::ordered_list, split_list::details::wrap_set_traits<T, Traits> >::type
267 typedef details::make_split_list_set< cds::urcu::gc< RCU >, T, typename Traits::ordered_list, split_list::details::wrap_set_traits<T, Traits> > maker;
268 typedef typename maker::type base_class;
272 typedef cds::urcu::gc< RCU > gc; ///< RCU-based garbage collector
273 typedef T value_type; ///< Type of value to be storedin the set
274 typedef Traits traits; ///< \p Traits template argument
276 // Note: ordered_list is not real ordered list type. Actual type is base_class::ordered_list
277 typedef typename maker::ordered_list ordered_list; ///< Underlying ordered list class
278 typedef typename base_class::key_comparator key_comparator; ///< key compare functor
280 /// Hash functor for \ref value_type and all its derivatives that you use
281 typedef typename base_class::hash hash;
282 typedef typename base_class::item_counter item_counter; ///< Item counter type
283 typedef typename base_class::stat stat; ///< Internal statistics
285 typedef typename base_class::rcu_lock rcu_lock ; ///< RCU scoped lock
286 /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
287 static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
291 typedef typename maker::cxx_node_allocator cxx_node_allocator;
292 typedef typename maker::node_type node_type;
296 /// pointer to extracted node
297 using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::ordered_list_traits::disposer >;
298 # ifdef CDS_DOXYGEN_INVOKED
299 /// pointer to the node for \p get() function
301 For \p LazyList, \p %raw_ptr is just pointer to \p value_type.
303 For \p MichaelList, \p %raw_ptr is \p cds::urcu::raw_ptr object giving access to \p value_type.
305 typedef implementation_defined raw_ptr;
308 typedef split_list::details::make_raw_ptr< value_type, typename base_class::ordered_list::raw_ptr, typename traits::ordered_list > raw_ptr_maker;
310 typedef typename raw_ptr_maker::raw_ptr raw_ptr;
315 template <typename Q, typename Func>
316 bool find_( Q& val, Func f )
318 return base_class::find( val, [&f]( node_type& item, Q& v ) { f(item.m_Value, v) ; } );
321 template <typename Q, typename Less, typename Func>
322 bool find_with_( Q& val, Less pred, Func f )
325 return base_class::find_with( val, typename maker::template predicate_wrapper<Less>::type(),
326 [&f]( node_type& item, Q& v ) { f(item.m_Value, v) ; } );
329 template <typename Q>
330 static node_type * alloc_node( Q const& v )
332 return cxx_node_allocator().New( v );
335 template <typename... Args>
336 static node_type * alloc_node( Args&&... args )
338 return cxx_node_allocator().MoveNew( std::forward<Args>(args)...);
341 static void free_node( node_type * pNode )
343 cxx_node_allocator().Delete( pNode );
346 struct node_disposer {
347 void operator()( node_type * pNode )
352 typedef std::unique_ptr< node_type, node_disposer > scoped_node_ptr;
354 bool insert_node( node_type * pNode )
356 assert( pNode != nullptr );
357 scoped_node_ptr p(pNode);
359 if ( base_class::insert( *pNode )) {
370 template <bool IsConst>
371 class iterator_type: protected base_class::template iterator_type<IsConst>
373 typedef typename base_class::template iterator_type<IsConst> iterator_base_class;
374 friend class SplitListSet;
377 /// Value pointer type (const for const iterator)
378 typedef typename cds::details::make_const_type<value_type, IsConst>::pointer value_ptr;
379 /// Value reference type (const for const iterator)
380 typedef typename cds::details::make_const_type<value_type, IsConst>::reference value_ref;
388 iterator_type( iterator_type const& src )
389 : iterator_base_class( src )
393 explicit iterator_type( iterator_base_class const& src )
394 : iterator_base_class( src )
398 /// Dereference operator
399 value_ptr operator ->() const
401 return &(iterator_base_class::operator->()->m_Value);
404 /// Dereference operator
405 value_ref operator *() const
407 return iterator_base_class::operator*().m_Value;
411 iterator_type& operator ++()
413 iterator_base_class::operator++();
417 /// Assignment operator
418 iterator_type& operator = (iterator_type const& src)
420 iterator_base_class::operator=(src);
424 /// Equality operator
426 bool operator ==(iterator_type<C> const& i ) const
428 return iterator_base_class::operator==(i);
431 /// Equality operator
433 bool operator !=(iterator_type<C> const& i ) const
435 return iterator_base_class::operator!=(i);
441 /// Initializes split-ordered list of default capacity
443 The default capacity is defined in bucket table constructor.
444 See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table
445 which selects by \p container::split_list::dynamic_bucket_table option.
451 /// Initializes split-ordered list
453 size_t nItemCount ///< estimated average of item count
454 , size_t nLoadFactor = 1 ///< load factor - average item count per bucket. Small integer up to 8, default is 1.
456 : base_class( nItemCount, nLoadFactor )
460 ///@name Forward iterators (thread-safe under RCU lock)
464 The forward iterator for Michael's set is based on \p OrderedList forward iterator and has some features:
465 - it has no post-increment operator
466 - it iterates items in unordered fashion
468 You may safely use iterators in multi-threaded environment only under RCU lock.
469 Otherwise, a crash is possible if another thread deletes the element the iterator points to.
471 The iterator interface:
475 // Default constructor
479 iterator( iterator const& src );
481 // Dereference operator
482 value_type * operator ->() const;
484 // Dereference operator
485 value_type& operator *() const;
487 // Preincrement operator
488 iterator& operator ++();
490 // Assignment operator
491 iterator& operator = (iterator const& src);
493 // Equality operators
494 bool operator ==(iterator const& i ) const;
495 bool operator !=(iterator const& i ) const;
499 typedef iterator_type<false> iterator;
501 /// Forward const iterator
502 typedef iterator_type<true> const_iterator;
504 /// Returns a forward iterator addressing the first element in a set
506 For empty set \code begin() == end() \endcode
510 return iterator( base_class::begin());
513 /// Returns an iterator that addresses the location succeeding the last element in a set
515 Do not use the value returned by <tt>end</tt> function to access any item.
516 The returned value can be used only to control reaching the end of the set.
517 For empty set \code begin() == end() \endcode
521 return iterator( base_class::end());
524 /// Returns a forward const iterator addressing the first element in a set
525 const_iterator begin() const
529 /// Returns a forward const iterator addressing the first element in a set
530 const_iterator cbegin() const
532 return const_iterator( base_class::cbegin());
535 /// Returns an const iterator that addresses the location succeeding the last element in a set
536 const_iterator end() const
540 /// Returns an const iterator that addresses the location succeeding the last element in a set
541 const_iterator cend() const
543 return const_iterator( base_class::cend());
550 The function creates a node with copy of \p val value
551 and then inserts the node created into the set.
553 The type \p Q should contain as minimum the complete key for the node.
554 The object of \p value_type should be constructible from a value of type \p Q.
555 In trivial case, \p Q is equal to \p value_type.
557 The function applies RCU lock internally.
559 Returns \p true if \p val is inserted into the set, \p false otherwise.
561 template <typename Q>
562 bool insert( Q const& val )
564 return insert_node( alloc_node( val ));
569 The function allows to split creating of new item into two part:
570 - create item with key only
571 - insert new item into the set
572 - if inserting is success, calls \p f functor to initialize value-field of \p val.
574 The functor signature is:
576 void func( value_type& val );
578 where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
579 \p val no any other changes could be made on this set's item by concurrent threads.
580 The user-defined functor is called only if the inserting is success.
582 The function applies RCU lock internally.
584 template <typename Q, typename Func>
585 bool insert( Q const& key, Func f )
587 scoped_node_ptr pNode( alloc_node( key ));
589 if ( base_class::insert( *pNode, [&f](node_type& node) { f( node.m_Value ) ; } )) {
596 /// Inserts data of type \p value_type created from \p args
598 Returns \p true if inserting successful, \p false otherwise.
600 The function applies RCU lock internally.
602 template <typename... Args>
603 bool emplace( Args&&... args )
605 return insert_node( alloc_node( std::forward<Args>(args)...));
608 /// Updates an element with given \p val
610 The operation performs inserting or changing data with lock-free manner.
612 If the \p val key not found in the set, then the new item created from \p val
613 is inserted into the set. Otherwise, the functor \p func is called with the item found.
614 The functor \p Func signature is:
617 void operator()( bool bNew, value_type& item, const Q& val );
622 - \p bNew - \p true if the item has been inserted, \p false otherwise
623 - \p item - item of the set
624 - \p val - argument \p val passed into the \p %ensure() function
626 The functor may change non-key fields of the \p item; however, \p func must guarantee
627 that during changing no any other modifications could be made on this item by concurrent threads.
629 The function applies RCU lock internally.
631 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
632 \p second is true if new item has been added or \p false if the item with \p key
633 already is in the set.
637 The operation performs inserting or changing data with lock-free manner.
639 If \p key is not found in the set, then \p key is inserted iff \p bAllowInsert is \p true.
640 Otherwise, the functor \p func is called with item found.
642 The functor signature is:
645 void operator()( bool bNew, value_type& item, const Q& val );
650 - \p bNew - \p true if the item has been inserted, \p false otherwise
651 - \p item - item of the set
652 - \p val - argument \p val passed into the \p %update() function
654 The functor may change non-key fields of the \p item.
656 The function applies RCU lock internally.
658 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
659 \p second is true if new item has been added or \p false if the item with \p key
660 already is in the map.
662 @warning For \ref cds_intrusive_MichaelList_rcu "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
663 \ref cds_intrusive_LazyList_rcu "LazyList" provides exclusive access to inserted item and does not require any node-level
666 template <typename Q, typename Func>
667 std::pair<bool, bool> update( Q const& val, Func func, bool bAllowInsert = true )
669 scoped_node_ptr pNode( alloc_node( val ));
671 std::pair<bool, bool> bRet = base_class::update( *pNode,
672 [&func, &val]( bool bNew, node_type& item, node_type const& /*val*/ ) {
673 func( bNew, item.m_Value, val );
675 if ( bRet.first && bRet.second )
680 // Dprecated, use update()
681 template <typename Q, typename Func>
682 std::pair<bool, bool> ensure( Q const& val, Func func )
684 return update( val, func, true );
688 /// Deletes \p key from the set
689 /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_val
691 Template parameter of type \p Q defines the key type searching in the list.
692 The set item comparator should be able to compare the values of type \p value_type
695 RCU \p synchronize method can be called. RCU should not be locked.
697 Return \p true if key is found and deleted, \p false otherwise
699 template <typename Q>
700 bool erase( Q const& key )
702 return base_class::erase( key );
705 /// Deletes the item from the set using \p pred predicate for searching
707 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_erase_val "erase(Q const&)"
708 but \p pred is used for key comparing.
709 \p Less functor has the interface like \p std::less.
710 \p Less must imply the same element order as the comparator used for building the set.
712 template <typename Q, typename Less>
713 bool erase_with( Q const& key, Less pred )
716 return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type());
719 /// Deletes \p key from the set
720 /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_func
722 The function searches an item with key \p key, calls \p f functor
723 and deletes the item. If \p key is not found, the functor is not called.
725 The functor \p Func interface:
728 void operator()(value_type const& val);
732 Template parameter of type \p Q defines the key type searching in the list.
733 The list item comparator should be able to compare the values of the type \p value_type
736 RCU \p synchronize method can be called. RCU should not be locked.
738 Return \p true if key is found and deleted, \p false otherwise
740 template <typename Q, typename Func>
741 bool erase( Q const& key, Func f )
743 return base_class::erase( key, [&f](node_type& node) { f( node.m_Value ); } );
746 /// Deletes the item from the set using \p pred predicate for searching
748 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_erase_func "erase(Q const&, Func)"
749 but \p pred is used for key comparing.
750 \p Less functor has the interface like \p std::less.
751 \p Less must imply the same element order as the comparator used for building the set.
753 template <typename Q, typename Less, typename Func>
754 bool erase_with( Q const& key, Less pred, Func f )
757 return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type(),
758 [&f](node_type& node) { f( node.m_Value ); } );
761 /// Extracts an item from the set
762 /** \anchor cds_nonintrusive_SplitListSet_rcu_extract
763 The function searches an item with key equal to \p key in the set,
764 unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
765 If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
767 Depends on \p bucket_type you should or should not lock RCU before calling of this function:
768 - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked
769 - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked
770 See ordered list implementation for details.
773 typedef cds::urcu::gc< general_buffered<> > rcu;
775 // Split-list set based on MichaelList by default
776 typedef cds::container::SplitListSet< rcu, Foo > splitlist_set;
778 splitlist_set theSet;
781 splitlist_set::exempt_ptr p;
783 // For MichaelList we should not lock RCU
785 // Now, you can apply extract function
786 p = theSet.extract( 10 );
788 // do something with p
792 // We may safely release p here
793 // release() passes the pointer to RCU reclamation cycle
797 template <typename Q>
798 exempt_ptr extract( Q const& key )
800 return exempt_ptr( base_class::extract_( key, key_comparator()));
803 /// Extracts an item from the set using \p pred predicate for searching
805 The function is an analog of \p extract(Q const&) but \p pred is used for key comparing.
806 \p Less functor has the interface like \p std::less.
807 \p pred must imply the same element order as the comparator used for building the set.
809 template <typename Q, typename Less>
810 exempt_ptr extract_with( Q const& key, Less pred )
813 return exempt_ptr( base_class::extract_with_( key, typename maker::template predicate_wrapper<Less>::type()));
816 /// Finds the key \p key
817 /** \anchor cds_nonintrusive_SplitListSet_rcu_find_func
819 The function searches the item with key equal to \p key and calls the functor \p f for item found.
820 The interface of \p Func functor is:
823 void operator()( value_type& item, Q& key );
826 where \p item is the item found, \p key is the <tt>find</tt> function argument.
828 The functor may change non-key fields of \p item. Note that the functor is only guarantee
829 that \p item cannot be disposed during functor is executing.
830 The functor does not serialize simultaneous access to the set's \p item. If such access is
831 possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
833 Note the hash functor specified for class \p Traits template parameter
834 should accept a parameter of type \p Q that can be not the same as \p value_type.
836 The function makes RCU lock internally.
838 The function returns \p true if \p key is found, \p false otherwise.
840 template <typename Q, typename Func>
841 bool find( Q& key, Func f )
843 return find_( key, f );
846 template <typename Q, typename Func>
847 bool find( Q const& key, Func f )
849 return find_( key, f );
853 /// Finds the key \p key using \p pred predicate for searching
855 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_find_func "find(Q&, Func)"
856 but \p pred is used for key comparing.
857 \p Less functor has the interface like \p std::less.
858 \p Less must imply the same element order as the comparator used for building the set.
860 template <typename Q, typename Less, typename Func>
861 bool find_with( Q& key, Less pred, Func f )
863 return find_with_( key, pred, f );
866 template <typename Q, typename Less, typename Func>
867 bool find_with( Q const& key, Less pred, Func f )
869 return find_with_( key, pred, f );
873 /// Checks whether the set contains \p key
875 The function searches the item with key equal to \p key
876 and returns \p true if it is found, and \p false otherwise.
878 Note the hash functor specified for class \p Traits template parameter
879 should accept a parameter of type \p Q that can be not the same as \p value_type.
880 Otherwise, you may use \p contains( Q const&, Less pred ) functions with explicit predicate for key comparing.
882 The function applies RCU lock internally.
884 template <typename Q>
885 bool contains( Q const& key )
887 return base_class::contains( key );
890 template <typename Q>
891 CDS_DEPRECATED("deprecated, use contains()")
892 bool find( Q const& key )
894 return contains( key );
898 /// Checks whether the map contains \p key using \p pred predicate for searching
900 The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
901 \p Less functor has the interface like \p std::less.
902 \p Less must imply the same element order as the comparator used for building the map.
904 template <typename Q, typename Less>
905 bool contains( Q const& key, Less pred )
908 return base_class::contains( key, typename maker::template predicate_wrapper<Less>::type());
911 template <typename Q, typename Less>
912 CDS_DEPRECATED("deprecated, use contains()")
913 bool find_with( Q const& key, Less pred )
915 return contains( key, pred );
919 /// Finds the key \p key and return the item found
920 /** \anchor cds_nonintrusive_SplitListSet_rcu_get
921 The function searches the item with key equal to \p key and returns the pointer to item found.
922 If \p key is not found it returns \p nullptr.
924 Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
926 RCU should be locked before call of this function.
927 Returned item is valid only while RCU is locked:
929 typedef cds::urcu::gc< general_buffered<> > rcu;
930 typedef cds::container::SplitListSet< rcu, Foo > splitlist_set;
931 splitlist_set theSet;
935 splitlist_set::rcu_lock lock;
937 foo * pVal = theSet.get( 5 );
942 // Unlock RCU by rcu_lock destructor
943 // pVal can be retired by disposer at any time after RCU has been unlocked
947 template <typename Q>
948 raw_ptr get( Q const& key )
950 return raw_ptr_maker::make( base_class::get( key ));
953 /// Finds the key \p key and return the item found
955 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_get "get(Q const&)"
956 but \p pred is used for comparing the keys.
958 \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
960 \p pred must imply the same element order as the comparator used for building the set.
962 template <typename Q, typename Less>
963 raw_ptr get_with( Q const& key, Less pred )
966 return raw_ptr_maker::make( base_class::get_with( key, typename maker::template predicate_wrapper<Less>::type()));
969 /// Clears the set (not atomic)
975 /// Checks if the set is empty
977 Emptiness is checked by item counting: if item count is zero then assume that the set is empty.
978 Thus, the correct item counting feature is an important part of split-list set implementation.
982 return base_class::empty();
985 /// Returns item count in the set
988 return base_class::size();
991 /// Returns internal statistics
992 stat const& statistics() const
994 return base_class::statistics();
997 /// Returns internal statistics for \p ordered_list
998 typename ordered_list::stat const& list_statistics() const
1000 return base_class::list_statistics();
1003 }} // namespace cds::container
1005 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H