2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
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& val ) { f(item.m_Value, val) ; } );
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& val ) { f(item.m_Value, val) ; } );
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 ) ) {
371 \p IsConst - constness boolean flag
373 The forward iterator for a split-list has the following features:
374 - it has no post-increment operator
375 - it depends on underlying ordered list iterator
376 - it is safe to iterate only inside RCU critical section
377 - deleting an item pointed by the iterator can cause to deadlock
379 Therefore, the use of iterators in concurrent environment is not good idea.
380 Use it for debug purpose only.
382 template <bool IsConst>
383 class iterator_type: protected base_class::template iterator_type<IsConst>
386 typedef typename base_class::template iterator_type<IsConst> iterator_base_class;
387 friend class SplitListSet;
390 /// Value pointer type (const for const iterator)
391 typedef typename cds::details::make_const_type<value_type, IsConst>::pointer value_ptr;
392 /// Value reference type (const for const iterator)
393 typedef typename cds::details::make_const_type<value_type, IsConst>::reference value_ref;
401 iterator_type( iterator_type const& src )
402 : iterator_base_class( src )
407 explicit iterator_type( iterator_base_class const& src )
408 : iterator_base_class( src )
413 /// Dereference operator
414 value_ptr operator ->() const
416 return &(iterator_base_class::operator->()->m_Value);
419 /// Dereference operator
420 value_ref operator *() const
422 return iterator_base_class::operator*().m_Value;
426 iterator_type& operator ++()
428 iterator_base_class::operator++();
432 /// Assignment operator
433 iterator_type& operator = (iterator_type const& src)
435 iterator_base_class::operator=(src);
439 /// Equality operator
441 bool operator ==(iterator_type<C> const& i ) const
443 return iterator_base_class::operator==(i);
446 /// Equality operator
448 bool operator !=(iterator_type<C> const& i ) const
450 return iterator_base_class::operator!=(i);
455 /// Initializes split-ordered list of default capacity
457 The default capacity is defined in bucket table constructor.
458 See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table
459 which selects by \p container::split_list::dynamic_bucket_table option.
465 /// Initializes split-ordered list
467 size_t nItemCount ///< estimated average of item count
468 , size_t nLoadFactor = 1 ///< load factor - average item count per bucket. Small integer up to 8, default is 1.
470 : base_class( nItemCount, nLoadFactor )
474 typedef iterator_type<false> iterator ; ///< Forward iterator
475 typedef iterator_type<true> const_iterator ; ///< Forward const iterator
477 /// Returns a forward iterator addressing the first element in a set
479 For empty set \code begin() == end() \endcode
483 return iterator( base_class::begin() );
486 /// Returns an iterator that addresses the location succeeding the last element in a set
488 Do not use the value returned by <tt>end</tt> function to access any item.
489 The returned value can be used only to control reaching the end of the set.
490 For empty set \code begin() == end() \endcode
494 return iterator( base_class::end() );
497 /// Returns a forward const iterator addressing the first element in a set
498 const_iterator begin() const
502 /// Returns a forward const iterator addressing the first element in a set
503 const_iterator cbegin() const
505 return const_iterator( base_class::cbegin() );
508 /// Returns an const iterator that addresses the location succeeding the last element in a set
509 const_iterator end() const
513 /// Returns an const iterator that addresses the location succeeding the last element in a set
514 const_iterator cend() const
516 return const_iterator( base_class::cend() );
522 The function creates a node with copy of \p val value
523 and then inserts the node created into the set.
525 The type \p Q should contain as minimum the complete key for the node.
526 The object of \p value_type should be constructible from a value of type \p Q.
527 In trivial case, \p Q is equal to \p value_type.
529 The function applies RCU lock internally.
531 Returns \p true if \p val is inserted into the set, \p false otherwise.
533 template <typename Q>
534 bool insert( Q const& val )
536 return insert_node( alloc_node( val ) );
541 The function allows to split creating of new item into two part:
542 - create item with key only
543 - insert new item into the set
544 - if inserting is success, calls \p f functor to initialize value-field of \p val.
546 The functor signature is:
548 void func( value_type& val );
550 where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
551 \p val no any other changes could be made on this set's item by concurrent threads.
552 The user-defined functor is called only if the inserting is success.
554 The function applies RCU lock internally.
556 template <typename Q, typename Func>
557 bool insert( Q const& key, Func f )
559 scoped_node_ptr pNode( alloc_node( key ));
561 if ( base_class::insert( *pNode, [&f](node_type& node) { f( node.m_Value ) ; } )) {
568 /// Inserts data of type \p value_type created from \p args
570 Returns \p true if inserting successful, \p false otherwise.
572 The function applies RCU lock internally.
574 template <typename... Args>
575 bool emplace( Args&&... args )
577 return insert_node( alloc_node( std::forward<Args>(args)...));
580 /// Ensures that the \p val exists in the set
582 The operation performs inserting or changing data with lock-free manner.
584 If the \p val key not found in the set, then the new item created from \p val
585 is inserted into the set. Otherwise, the functor \p func is called with the item found.
586 The functor \p Func 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 %ensure() function
598 The functor may change non-key fields of the \p item; however, \p func must guarantee
599 that during changing no any other modifications could be made on this item by concurrent threads.
601 The function applies RCU lock internally.
603 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
604 \p second is true if new item has been added or \p false if the item with \p key
605 already is in the set.
609 The operation performs inserting or changing data with lock-free manner.
611 If \p key is not found in the set, then \p key is inserted iff \p bAllowInsert is \p true.
612 Otherwise, the functor \p func is called with item found.
614 The functor 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 %update() function
626 The functor may change non-key fields of the \p item.
628 The function applies RCU lock internally.
630 Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
631 \p second is true if new item has been added or \p false if the item with \p key
632 already is in the map.
634 @warning For \ref cds_intrusive_MichaelList_rcu "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
635 \ref cds_intrusive_LazyList_rcu "LazyList" provides exclusive access to inserted item and does not require any node-level
638 template <typename Q, typename Func>
639 std::pair<bool, bool> update( Q const& val, Func func, bool bAllowInsert = true )
641 scoped_node_ptr pNode( alloc_node( val ));
643 std::pair<bool, bool> bRet = base_class::update( *pNode,
644 [&func, &val]( bool bNew, node_type& item, node_type const& /*val*/ ) {
645 func( bNew, item.m_Value, val );
647 if ( bRet.first && bRet.second )
652 // Dprecated, use update()
653 template <typename Q, typename Func>
654 std::pair<bool, bool> ensure( Q const& val, Func func )
656 return update( val, func, true );
660 /// Deletes \p key from the set
661 /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_val
663 Template parameter of type \p Q defines the key type searching in the list.
664 The set item comparator should be able to compare the values of type \p value_type
667 RCU \p synchronize method can be called. RCU should not be locked.
669 Return \p true if key is found and deleted, \p false otherwise
671 template <typename Q>
672 bool erase( Q const& key )
674 return base_class::erase( key );
677 /// Deletes the item from the set using \p pred predicate for searching
679 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_erase_val "erase(Q const&)"
680 but \p pred is used for key comparing.
681 \p Less functor has the interface like \p std::less.
682 \p Less must imply the same element order as the comparator used for building the set.
684 template <typename Q, typename Less>
685 bool erase_with( Q const& key, Less pred )
688 return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type() );
691 /// Deletes \p key from the set
692 /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_func
694 The function searches an item with key \p key, calls \p f functor
695 and deletes the item. If \p key is not found, the functor is not called.
697 The functor \p Func interface:
700 void operator()(value_type const& val);
704 Template parameter of type \p Q defines the key type searching in the list.
705 The list item comparator should be able to compare the values of the type \p value_type
708 RCU \p synchronize method can be called. RCU should not be locked.
710 Return \p true if key is found and deleted, \p false otherwise
712 template <typename Q, typename Func>
713 bool erase( Q const& key, Func f )
715 return base_class::erase( key, [&f](node_type& node) { f( node.m_Value ); } );
718 /// Deletes the item from the set using \p pred predicate for searching
720 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_erase_func "erase(Q const&, Func)"
721 but \p pred is used for key comparing.
722 \p Less functor has the interface like \p std::less.
723 \p Less must imply the same element order as the comparator used for building the set.
725 template <typename Q, typename Less, typename Func>
726 bool erase_with( Q const& key, Less pred, Func f )
729 return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type(),
730 [&f](node_type& node) { f( node.m_Value ); } );
733 /// Extracts an item from the set
734 /** \anchor cds_nonintrusive_SplitListSet_rcu_extract
735 The function searches an item with key equal to \p key in the set,
736 unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
737 If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
739 Depends on \p bucket_type you should or should not lock RCU before calling of this function:
740 - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked
741 - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked
742 See ordered list implementation for details.
745 typedef cds::urcu::gc< general_buffered<> > rcu;
747 // Split-list set based on MichaelList by default
748 typedef cds::container::SplitListSet< rcu, Foo > splitlist_set;
750 splitlist_set theSet;
753 splitlist_set::exempt_ptr p;
755 // For MichaelList we should not lock RCU
757 // Now, you can apply extract function
758 p = theSet.extract( 10 );
760 // do something with p
764 // We may safely release p here
765 // release() passes the pointer to RCU reclamation cycle
769 template <typename Q>
770 exempt_ptr extract( Q const& key )
772 return exempt_ptr( base_class::extract_( key, key_comparator() ));
775 /// Extracts an item from the set using \p pred predicate for searching
777 The function is an analog of \p extract(Q const&) but \p pred is used for key comparing.
778 \p Less functor has the interface like \p std::less.
779 \p pred must imply the same element order as the comparator used for building the set.
781 template <typename Q, typename Less>
782 exempt_ptr extract_with( Q const& key, Less pred )
785 return exempt_ptr( base_class::extract_with_( key, typename maker::template predicate_wrapper<Less>::type()));
788 /// Finds the key \p key
789 /** \anchor cds_nonintrusive_SplitListSet_rcu_find_func
791 The function searches the item with key equal to \p key and calls the functor \p f for item found.
792 The interface of \p Func functor is:
795 void operator()( value_type& item, Q& key );
798 where \p item is the item found, \p key is the <tt>find</tt> function argument.
800 The functor may change non-key fields of \p item. Note that the functor is only guarantee
801 that \p item cannot be disposed during functor is executing.
802 The functor does not serialize simultaneous access to the set's \p item. If such access is
803 possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
805 Note the hash functor specified for class \p Traits template parameter
806 should accept a parameter of type \p Q that can be not the same as \p value_type.
808 The function makes RCU lock internally.
810 The function returns \p true if \p key is found, \p false otherwise.
812 template <typename Q, typename Func>
813 bool find( Q& key, Func f )
815 return find_( key, f );
818 template <typename Q, typename Func>
819 bool find( Q const& key, Func f )
821 return find_( key, f );
825 /// Finds the key \p key using \p pred predicate for searching
827 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_find_func "find(Q&, Func)"
828 but \p pred is used for key comparing.
829 \p Less functor has the interface like \p std::less.
830 \p Less must imply the same element order as the comparator used for building the set.
832 template <typename Q, typename Less, typename Func>
833 bool find_with( Q& key, Less pred, Func f )
835 return find_with_( key, pred, f );
838 template <typename Q, typename Less, typename Func>
839 bool find_with( Q const& key, Less pred, Func f )
841 return find_with_( key, pred, f );
845 /// Checks whether the set contains \p key
847 The function searches the item with key equal to \p key
848 and returns \p true if it is found, and \p false otherwise.
850 Note the hash functor specified for class \p Traits template parameter
851 should accept a parameter of type \p Q that can be not the same as \p value_type.
852 Otherwise, you may use \p contains( Q const&, Less pred ) functions with explicit predicate for key comparing.
854 The function applies RCU lock internally.
856 template <typename Q>
857 bool contains( Q const& key )
859 return base_class::contains( key );
862 template <typename Q>
863 CDS_DEPRECATED("deprecated, use contains()")
864 bool find( Q const& key )
866 return contains( key );
870 /// Checks whether the map contains \p key using \p pred predicate for searching
872 The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
873 \p Less functor has the interface like \p std::less.
874 \p Less must imply the same element order as the comparator used for building the map.
876 template <typename Q, typename Less>
877 bool contains( Q const& key, Less pred )
880 return base_class::contains( key, typename maker::template predicate_wrapper<Less>::type() );
883 template <typename Q, typename Less>
884 CDS_DEPRECATED("deprecated, use contains()")
885 bool find_with( Q const& key, Less pred )
887 return contains( key, pred );
891 /// Finds the key \p key and return the item found
892 /** \anchor cds_nonintrusive_SplitListSet_rcu_get
893 The function searches the item with key equal to \p key and returns the pointer to item found.
894 If \p key is not found it returns \p nullptr.
896 Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
898 RCU should be locked before call of this function.
899 Returned item is valid only while RCU is locked:
901 typedef cds::urcu::gc< general_buffered<> > rcu;
902 typedef cds::container::SplitListSet< rcu, Foo > splitlist_set;
903 splitlist_set theSet;
907 splitlist_set::rcu_lock lock;
909 foo * pVal = theSet.get( 5 );
914 // Unlock RCU by rcu_lock destructor
915 // pVal can be retired by disposer at any time after RCU has been unlocked
919 template <typename Q>
920 raw_ptr get( Q const& key )
922 return raw_ptr_maker::make( base_class::get( key ));
925 /// Finds the key \p key and return the item found
927 The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_get "get(Q const&)"
928 but \p pred is used for comparing the keys.
930 \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
932 \p pred must imply the same element order as the comparator used for building the set.
934 template <typename Q, typename Less>
935 raw_ptr get_with( Q const& key, Less pred )
938 return raw_ptr_maker::make( base_class::get_with( key, typename maker::template predicate_wrapper<Less>::type()));
941 /// Clears the set (not atomic)
947 /// Checks if the set is empty
949 Emptiness is checked by item counting: if item count is zero then assume that the set is empty.
950 Thus, the correct item counting feature is an important part of split-list set implementation.
954 return base_class::empty();
957 /// Returns item count in the set
960 return base_class::size();
963 /// Returns internal statistics
964 stat const& statistics() const
966 return base_class::statistics();
969 }} // namespace cds::container
971 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_RCU_H