3 #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H
4 #define CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H
6 #include <cds/intrusive/split_list_rcu.h>
7 #include <cds/container/details/make_split_list_set.h>
8 #include <cds/urcu/exempt_ptr.h>
10 namespace cds { namespace container {
13 namespace split_list { namespace details {
22 #ifdef CDSLIB_CONTAINER_DETAILS_MICHAEL_LIST_BASE_H
23 template <typename T, class RawPtr>
24 class make_raw_ptr< T, RawPtr, cds::container::michael_list_tag >
26 typedef RawPtr intrusive_raw_ptr;
27 typedef typename intrusive_raw_ptr::value_type node_type;
30 struct raw_ptr_converter
32 value_type * operator()( node_type * p ) const
34 return p ? &p->m_Value : nullptr;
37 value_type& operator()( node_type& n ) const
42 value_type const& operator()( node_type const& n ) const
48 typedef cds::urcu::raw_ptr_adaptor< value_type, intrusive_raw_ptr, raw_ptr_converter > raw_ptr;
50 static raw_ptr make( intrusive_raw_ptr&& p )
52 return raw_ptr(std::move( p ));
57 #ifdef CDSLIB_CONTAINER_DETAILS_LAZY_LIST_BASE_H
58 template <typename T, typename RawPtr>
59 class make_raw_ptr< T, RawPtr, cds::container::lazy_list_tag >
61 typedef RawPtr node_type_pointer;
65 typedef value_type * raw_ptr;
67 static raw_ptr make( node_type_pointer p )
69 return p ? &p->m_Value : nullptr;
73 }} //namespace split_list::details
76 /// Split-ordered list set (template specialization for \ref cds_urcu_desc "RCU")
77 /** @ingroup cds_nonintrusive_set
78 \anchor cds_nonintrusive_SplitListSet_rcu
80 Hash table implementation based on split-ordered list algorithm discovered by Ori Shalev and Nir Shavit, see
81 - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables"
82 - [2008] Nir Shavit "The Art of Multiprocessor Programming"
84 See \p intrusive::SplitListSet for a brief description of the split-list algorithm.
87 - \p RCU - one of \ref cds_urcu_gc "RCU type"
88 - \p T - type of the value to be stored in the split-list.
89 - \p Traits - type traits, default is \p split_list::traits. Instead of declaring \p split_list::traits -based
90 struct you can apply option-based notation with \p split_list::make_traits metafunction.
94 The class supports a forward iterator (\ref iterator and \ref const_iterator).
95 The iteration is unordered.
97 You may iterate over split-list set items only under RCU lock.
98 Only in this case the iterator is thread-safe since
99 while RCU is locked any set's item cannot be reclaimed.
101 @warning The iterator object cannot be passed between threads
103 \warning Due to concurrent nature of skip-list set it is not guarantee that you can iterate
104 all elements in the set: any concurrent deletion can exclude the element
105 pointed by the iterator from the set, and your iteration can be terminated
106 before end of the set. Therefore, such iteration is more suitable for debugging purposes
108 The iterator class supports the following minimalistic interface:
115 iterator( iterator const& s);
117 value_type * operator ->() const;
118 value_type& operator *() const;
121 iterator& operator ++();
124 iterator& operator = (const iterator& src);
126 bool operator ==(iterator const& i ) const;
127 bool operator !=(iterator const& i ) const;
130 Note, the iterator object returned by \p end(), \p cend() member functions points to \p nullptr and should not be dereferenced.
134 You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list
135 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
136 and \p LazyList as ordered list implementation. So, you beginning your program with following include:
138 #include <cds/urcu/general_buffered.h>
139 #include <cds/container/lazy_list_rcu.h>
140 #include <cds/container/split_list_set_rcu.h>
142 namespace cc = cds::container;
144 // The data belonged to split-ordered list
146 int nKey; // key field
147 std::string strValue ; // value field
150 The inclusion order is important:
151 - first, include one of \ref cds_urcu_gc "RCU implementation" (<tt>cds/urcu/general_buffered.h</tt> in our case)
152 - second, include file for ordered-list implementation (for this example, <tt>cds/container/lazy_list_rcu.h</tt>),
153 - then, the header for RCU-based split-list set <tt>cds/container/split_list_set_rcu.h</tt>.
155 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.
156 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
157 object by the key of type \p int and by the value of type \p foo.
159 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.
160 The split-list requires significant support from underlying ordered list class and it is not good idea to dive you
161 into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface.
166 size_t operator()( int key ) const { return std::hash( key ) ; }
167 size_t operator()( foo const& item ) const { return std::hash( item.nKey ) ; }
172 bool operator()(int i, foo const& f ) const { return i < f.nKey ; }
173 bool operator()(foo const& f, int i ) const { return f.nKey < i ; }
174 bool operator()(foo const& f1, foo const& f2) const { return f1.nKey < f2.nKey; }
177 // SplitListSet traits
178 struct foo_set_traits: public cc::split_list::traits
180 typedef cc::lazy_list_tag ordered_list ; // what type of ordered list we want to use
181 typedef foo_hash hash ; // hash functor for our data stored in split-list set
183 // Type traits for our LazyList class
184 struct ordered_list_traits: public cc::lazy_list::traits
186 typedef foo_less less ; // use our foo_less as comparator to order list nodes
191 Now you are ready to declare our set class based on \p %SplitListSet:
193 typedef cc::SplitListSet< cds::urcu::gc<cds::urcu::general_buffered<> >, foo, foo_set_traits > foo_set;
196 You may use the modern option-based declaration instead of classic type-traits-based one:
198 typedef cc::SplitListSet<
199 cds::urcu::gc<cds::urcu::general_buffered<> > // RCU type used
200 ,foo // type of data stored
201 ,cc::split_list::make_traits< // metafunction to build split-list traits
202 cc::split_list::ordered_list<cc::lazy_list_tag> // tag for underlying ordered list implementation
203 ,cc::opt::hash< foo_hash > // hash functor
204 ,cc::split_list::ordered_list_traits< // ordered list traits
205 cc::lazy_list::make_traits< // metafunction to build lazy list traits
206 cc::opt::less< foo_less > // less-based compare functor
212 In case of option-based declaration using \p split_list::make_traits metafunction
213 the struct \p foo_set_traits is not required.
215 Now, the set of type \p foo_set is ready to use in your program.
217 Note that in this example we show only mandatory \p traits parts, optional ones is the default and they are inherited
218 from \p container::split_list::traits.
219 There are many other options for deep tuning of the split-list and ordered-list containers.
224 #ifdef CDS_DOXYGEN_INVOKED
225 class Traits = split_list::traits
230 class SplitListSet< cds::urcu::gc< RCU >, T, Traits >:
231 #ifdef CDS_DOXYGEN_INVOKED
232 protected intrusive::SplitListSet< cds::urcu::gc< RCU >, T, typename Traits::ordered_list, Traits >
234 protected details::make_split_list_set< cds::urcu::gc< RCU >, T, typename Traits::ordered_list, split_list::details::wrap_set_traits<T, Traits> >::type
239 typedef details::make_split_list_set< cds::urcu::gc< RCU >, T, typename Traits::ordered_list, split_list::details::wrap_set_traits<T, Traits> > maker;
240 typedef typename maker::type base_class;
244 typedef cds::urcu::gc< RCU > gc; ///< RCU-based garbage collector
245 typedef T value_type; ///< Type of value to be storedin the set
246 typedef Traits traits; ///< \p Traits template argument
248 // Note: ordered_list is not real ordered list type. Actual type is base_class::ordered_list
249 typedef typename maker::ordered_list ordered_list; ///< Underlying ordered list class
250 typedef typename base_class::key_comparator key_comparator; ///< key compare functor
252 /// Hash functor for \ref value_type and all its derivatives that you use
253 typedef typename base_class::hash hash;
254 typedef typename base_class::item_counter item_counter; ///< Item counter type
255 typedef typename base_class::stat stat; ///< Internal statistics
257 typedef typename base_class::rcu_lock rcu_lock ; ///< RCU scoped lock
258 /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
259 static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
263 typedef typename maker::cxx_node_allocator cxx_node_allocator;
264 typedef typename maker::node_type node_type;
268 /// pointer to extracted node
269 using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::ordered_list_traits::disposer >;
270 # ifdef CDS_DOXYGEN_INVOKED
271 /// pointer to the node for \p get() function
273 For \p LazyList, \p %raw_ptr is just pointer to \p value_type.
275 For \p MichaelList, \p %raw_ptr is \p cds::urcu::raw_ptr object giving access to \p value_type.
277 typedef implementation_defined raw_ptr;
280 typedef split_list::details::make_raw_ptr< value_type, typename base_class::ordered_list::raw_ptr, typename traits::ordered_list > raw_ptr_maker;
282 typedef typename raw_ptr_maker::raw_ptr raw_ptr;
287 template <typename Q, typename Func>
288 bool find_( Q& val, Func f )
290 return base_class::find( val, [&f]( node_type& item, Q& val ) { f(item.m_Value, val) ; } );
293 template <typename Q, typename Less, typename Func>
294 bool find_with_( Q& val, Less pred, Func f )
297 return base_class::find_with( val, typename maker::template predicate_wrapper<Less>::type(),
298 [&f]( node_type& item, Q& val ) { f(item.m_Value, val) ; } );
301 template <typename Q>
302 static node_type * alloc_node( Q const& v )
304 return cxx_node_allocator().New( v );
307 template <typename... Args>
308 static node_type * alloc_node( Args&&... args )
310 return cxx_node_allocator().MoveNew( std::forward<Args>(args)...);
313 static void free_node( node_type * pNode )
315 cxx_node_allocator().Delete( pNode );
318 struct node_disposer {
319 void operator()( node_type * pNode )
324 typedef std::unique_ptr< node_type, node_disposer > scoped_node_ptr;
326 bool insert_node( node_type * pNode )
328 assert( pNode != nullptr );
329 scoped_node_ptr p(pNode);
331 if ( base_class::insert( *pNode ) ) {
343 \p IsConst - constness boolean flag
345 The forward iterator for a split-list has the following features:
346 - it has no post-increment operator
347 - it depends on underlying ordered list iterator
348 - it is safe to iterate only inside RCU critical section
349 - deleting an item pointed by the iterator can cause to deadlock
351 Therefore, the use of iterators in concurrent environment is not good idea.
352 Use it for debug purpose only.
354 template <bool IsConst>
355 class iterator_type: protected base_class::template iterator_type<IsConst>
358 typedef typename base_class::template iterator_type<IsConst> iterator_base_class;
359 friend class SplitListSet;
362 /// Value pointer type (const for const iterator)
363 typedef typename cds::details::make_const_type<value_type, IsConst>::pointer value_ptr;
364 /// Value reference type (const for const iterator)
365 typedef typename cds::details::make_const_type<value_type, IsConst>::reference value_ref;
373 iterator_type( iterator_type const& src )
374 : iterator_base_class( src )
379 explicit iterator_type( iterator_base_class const& src )
380 : iterator_base_class( src )
385 /// Dereference operator
386 value_ptr operator ->() const
388 return &(iterator_base_class::operator->()->m_Value);
391 /// Dereference operator
392 value_ref operator *() const
394 return iterator_base_class::operator*().m_Value;
398 iterator_type& operator ++()
400 iterator_base_class::operator++();
404 /// Assignment operator
405 iterator_type& operator = (iterator_type const& src)
407 iterator_base_class::operator=(src);
411 /// Equality operator
413 bool operator ==(iterator_type<C> const& i ) const
415 return iterator_base_class::operator==(i);
418 /// Equality operator
420 bool operator !=(iterator_type<C> const& i ) const
422 return iterator_base_class::operator!=(i);
427 /// Initializes split-ordered list of default capacity
429 The default capacity is defined in bucket table constructor.
430 See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table
431 which selects by \p container::split_list::dynamic_bucket_table option.
437 /// Initializes split-ordered list
439 size_t nItemCount ///< estimated average of item count
440 , size_t nLoadFactor = 1 ///< load factor - average item count per bucket. Small integer up to 8, default is 1.
442 : base_class( nItemCount, nLoadFactor )
446 typedef iterator_type<false> iterator ; ///< Forward iterator
447 typedef iterator_type<true> const_iterator ; ///< Forward const iterator
449 /// Returns a forward iterator addressing the first element in a set
451 For empty set \code begin() == end() \endcode
455 return iterator( base_class::begin() );
458 /// Returns an iterator that addresses the location succeeding the last element in a set
460 Do not use the value returned by <tt>end</tt> function to access any item.
461 The returned value can be used only to control reaching the end of the set.
462 For empty set \code begin() == end() \endcode
466 return iterator( base_class::end() );
469 /// Returns a forward const iterator addressing the first element in a set
470 const_iterator begin() const
474 /// Returns a forward const iterator addressing the first element in a set
475 const_iterator cbegin() const
477 return const_iterator( base_class::cbegin() );
480 /// Returns an const iterator that addresses the location succeeding the last element in a set
481 const_iterator end() const
485 /// Returns an const iterator that addresses the location succeeding the last element in a set
486 const_iterator cend() const
488 return const_iterator( base_class::cend() );
494 The function creates a node with copy of \p val value
495 and then inserts the node created into the set.
497 The type \p Q should contain as minimum the complete key for the node.
498 The object of \p value_type should be constructible from a value of type \p Q.
499 In trivial case, \p Q is equal to \p value_type.
501 The function applies RCU lock internally.
503 Returns \p true if \p val is inserted into the set, \p false otherwise.
505 template <typename Q>
506 bool insert( Q const& val )
508 return insert_node( alloc_node( val ) );
513 The function allows to split creating of new item into two part:
514 - create item with key only
515 - insert new item into the set
516 - if inserting is success, calls \p f functor to initialize value-field of \p val.
518 The functor signature is:
520 void func( value_type& val );
522 where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
523 \p val no any other changes could be made on this set's item by concurrent threads.
524 The user-defined functor is called only if the inserting is success.
526 The function applies RCU lock internally.
528 template <typename Q, typename Func>
529 bool insert( Q const& key, Func f )
531 scoped_node_ptr pNode( alloc_node( key ));
533 if ( base_class::insert( *pNode, [&f](node_type& node) { f( node.m_Value ) ; } )) {
540 /// Inserts data of type \p value_type created from \p args
542 Returns \p true if inserting successful, \p false otherwise.
544 The function applies RCU lock internally.
546 template <typename... Args>
547 bool emplace( Args&&... args )
549 return insert_node( alloc_node( std::forward<Args>(args)...));
552 /// Ensures that the \p val exists in the set
554 The operation performs inserting or changing data with lock-free manner.
556 If the \p val key not found in the set, then the new item created from \p val
557 is inserted into the set. Otherwise, the functor \p func is called with the item found.
558 The functor \p Func signature is:
561 void operator()( bool bNew, value_type& item, const Q& val );
566 - \p bNew - \p true if the item has been inserted, \p false otherwise
567 - \p item - item of the set
568 - \p val - argument \p val passed into the \p %ensure() function
570 The functor may change non-key fields of the \p item; however, \p func must guarantee
571 that during changing no any other modifications could be made on this item by concurrent threads.
573 The function applies RCU lock internally.
575 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
576 \p second is true if new item has been added or \p false if the item with \p key
577 already is in the set.
581 The operation performs inserting or changing data with lock-free manner.
583 If \p key is not found in the set, then \p key is inserted iff \p bAllowInsert is \p true.
584 Otherwise, the functor \p func is called with item found.
586 The functor signature is:
589 void operator()( bool bNew, value_type& item, const Q& val );
594 - \p bNew - \p true if the item has been inserted, \p false otherwise
595 - \p item - item of the set
596 - \p val - argument \p val passed into the \p %update() function
598 The functor may change non-key fields of the \p item.
600 The function applies RCU lock internally.
602 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
603 \p second is true if new item has been added or \p false if the item with \p key
604 already is in the map.
606 @warning For \ref cds_intrusive_MichaelList_rcu "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
607 \ref cds_intrusive_LazyList_rcu "LazyList" provides exclusive access to inserted item and does not require any node-level
610 template <typename Q, typename Func>
611 std::pair<bool, bool> update( Q const& val, Func func, bool bAllowInsert = true )
613 scoped_node_ptr pNode( alloc_node( val ));
615 std::pair<bool, bool> bRet = base_class::update( *pNode,
616 [&func, &val]( bool bNew, node_type& item, node_type const& /*val*/ ) {
617 func( bNew, item.m_Value, val );
619 if ( bRet.first && bRet.second )
624 // Dprecated, use update()
625 template <typename Q, typename Func>
626 std::pair<bool, bool> ensure( Q const& val, Func func )
628 return update( val, func, true );
632 /// Deletes \p key from the set
633 /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_val
635 Template parameter of type \p Q defines the key type searching in the list.
636 The set item comparator should be able to compare the values of type \p value_type
639 RCU \p synchronize method can be called. RCU should not be locked.
641 Return \p true if key is found and deleted, \p false otherwise
643 template <typename Q>
644 bool erase( Q const& key )
646 return base_class::erase( key );
649 /// Deletes the item from the set using \p pred predicate for searching
651 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_erase_val "erase(Q const&)"
652 but \p pred is used for key comparing.
653 \p Less functor has the interface like \p std::less.
654 \p Less must imply the same element order as the comparator used for building the set.
656 template <typename Q, typename Less>
657 bool erase_with( Q const& key, Less pred )
660 return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type() );
663 /// Deletes \p key from the set
664 /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_func
666 The function searches an item with key \p key, calls \p f functor
667 and deletes the item. If \p key is not found, the functor is not called.
669 The functor \p Func interface:
672 void operator()(value_type const& val);
676 Template parameter of type \p Q defines the key type searching in the list.
677 The list item comparator should be able to compare the values of the type \p value_type
680 RCU \p synchronize method can be called. RCU should not be locked.
682 Return \p true if key is found and deleted, \p false otherwise
684 template <typename Q, typename Func>
685 bool erase( Q const& key, Func f )
687 return base_class::erase( key, [&f](node_type& node) { f( node.m_Value ); } );
690 /// Deletes the item from the set using \p pred predicate for searching
692 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_erase_func "erase(Q const&, Func)"
693 but \p pred is used for key comparing.
694 \p Less functor has the interface like \p std::less.
695 \p Less must imply the same element order as the comparator used for building the set.
697 template <typename Q, typename Less, typename Func>
698 bool erase_with( Q const& key, Less pred, Func f )
701 return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type(),
702 [&f](node_type& node) { f( node.m_Value ); } );
705 /// Extracts an item from the set
706 /** \anchor cds_nonintrusive_SplitListSet_rcu_extract
707 The function searches an item with key equal to \p key in the set,
708 unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
709 If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
711 Depends on \p bucket_type you should or should not lock RCU before calling of this function:
712 - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked
713 - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked
714 See ordered list implementation for details.
717 typedef cds::urcu::gc< general_buffered<> > rcu;
719 // Split-list set based on MichaelList by default
720 typedef cds::container::SplitListSet< rcu, Foo > splitlist_set;
722 splitlist_set theSet;
725 splitlist_set::exempt_ptr p;
727 // For MichaelList we should not lock RCU
729 // Now, you can apply extract function
730 p = theSet.extract( 10 );
732 // do something with p
736 // We may safely release p here
737 // release() passes the pointer to RCU reclamation cycle
741 template <typename Q>
742 exempt_ptr extract( Q const& key )
744 return exempt_ptr( base_class::extract_( key, key_comparator() ));
747 /// Extracts an item from the set using \p pred predicate for searching
749 The function is an analog of \p extract(Q const&) but \p pred is used for key comparing.
750 \p Less functor has the interface like \p std::less.
751 \p pred must imply the same element order as the comparator used for building the set.
753 template <typename Q, typename Less>
754 exempt_ptr extract_with( Q const& key, Less pred )
757 return exempt_ptr( base_class::extract_with_( key, typename maker::template predicate_wrapper<Less>::type()));
760 /// Finds the key \p key
761 /** \anchor cds_nonintrusive_SplitListSet_rcu_find_func
763 The function searches the item with key equal to \p key and calls the functor \p f for item found.
764 The interface of \p Func functor is:
767 void operator()( value_type& item, Q& key );
770 where \p item is the item found, \p key is the <tt>find</tt> function argument.
772 The functor may change non-key fields of \p item. Note that the functor is only guarantee
773 that \p item cannot be disposed during functor is executing.
774 The functor does not serialize simultaneous access to the set's \p item. If such access is
775 possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
777 Note the hash functor specified for class \p Traits template parameter
778 should accept a parameter of type \p Q that can be not the same as \p value_type.
780 The function makes RCU lock internally.
782 The function returns \p true if \p key is found, \p false otherwise.
784 template <typename Q, typename Func>
785 bool find( Q& key, Func f )
787 return find_( key, f );
790 template <typename Q, typename Func>
791 bool find( Q const& key, Func f )
793 return find_( key, f );
797 /// Finds the key \p key using \p pred predicate for searching
799 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_find_func "find(Q&, Func)"
800 but \p pred is used for key comparing.
801 \p Less functor has the interface like \p std::less.
802 \p Less must imply the same element order as the comparator used for building the set.
804 template <typename Q, typename Less, typename Func>
805 bool find_with( Q& key, Less pred, Func f )
807 return find_with_( key, pred, f );
810 template <typename Q, typename Less, typename Func>
811 bool find_with( Q const& key, Less pred, Func f )
813 return find_with_( key, pred, f );
817 /// Checks whether the set contains \p key
819 The function searches the item with key equal to \p key
820 and returns \p true if it is found, and \p false otherwise.
822 Note the hash functor specified for class \p Traits template parameter
823 should accept a parameter of type \p Q that can be not the same as \p value_type.
824 Otherwise, you may use \p contains( Q const&, Less pred ) functions with explicit predicate for key comparing.
826 The function applies RCU lock internally.
828 template <typename Q>
829 bool contains( Q const& key )
831 return base_class::contains( key );
834 template <typename Q>
835 CDS_DEPRECATED("deprecated, use contains()")
836 bool find( Q const& key )
838 return contains( key );
842 /// Checks whether the map contains \p key using \p pred predicate for searching
844 The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
845 \p Less functor has the interface like \p std::less.
846 \p Less must imply the same element order as the comparator used for building the map.
848 template <typename Q, typename Less>
849 bool contains( Q const& key, Less pred )
852 return base_class::contains( key, typename maker::template predicate_wrapper<Less>::type() );
855 template <typename Q, typename Less>
856 CDS_DEPRECATED("deprecated, use contains()")
857 bool find_with( Q const& key, Less pred )
859 return contains( key, pred );
863 /// Finds the key \p key and return the item found
864 /** \anchor cds_nonintrusive_SplitListSet_rcu_get
865 The function searches the item with key equal to \p key and returns the pointer to item found.
866 If \p key is not found it returns \p nullptr.
868 Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
870 RCU should be locked before call of this function.
871 Returned item is valid only while RCU is locked:
873 typedef cds::urcu::gc< general_buffered<> > rcu;
874 typedef cds::container::SplitListSet< rcu, Foo > splitlist_set;
875 splitlist_set theSet;
879 splitlist_set::rcu_lock lock;
881 foo * pVal = theSet.get( 5 );
886 // Unlock RCU by rcu_lock destructor
887 // pVal can be retired by disposer at any time after RCU has been unlocked
891 template <typename Q>
892 raw_ptr get( Q const& key )
894 return raw_ptr_maker::make( base_class::get( key ));
897 /// Finds the key \p key and return the item found
899 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_get "get(Q const&)"
900 but \p pred is used for comparing the keys.
902 \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
904 \p pred must imply the same element order as the comparator used for building the set.
906 template <typename Q, typename Less>
907 raw_ptr get_with( Q const& key, Less pred )
910 return raw_ptr_maker::make( base_class::get_with( key, typename maker::template predicate_wrapper<Less>::type()));
913 /// Clears the set (not atomic)
919 /// Checks if the set is empty
921 Emptiness is checked by item counting: if item count is zero then assume that the set is empty.
922 Thus, the correct item counting feature is an important part of split-list set implementation.
926 return base_class::empty();
929 /// Returns item count in the set
932 return base_class::size();
935 /// Returns internal statistics
936 stat const& statistics() const
938 return base_class::statistics();
941 }} // namespace cds::container
943 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H