Changed algorithm of IterableList detecting
[libcds.git] / cds / container / split_list_set.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
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.
18
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.
29 */
30
31 #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_H
32 #define CDSLIB_CONTAINER_SPLIT_LIST_SET_H
33
34 #include <cds/intrusive/split_list.h>
35 #include <cds/container/details/make_split_list_set.h>
36
37 namespace cds { namespace container {
38
39     /// Split-ordered list set
40     /** @ingroup cds_nonintrusive_set
41         \anchor cds_nonintrusive_SplitListSet_hp
42
43         Hash table implementation based on split-ordered list algorithm discovered by Ori Shalev and Nir Shavit, see
44         - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables"
45         - [2008] Nir Shavit "The Art of Multiprocessor Programming"
46
47         See \p intrusive::SplitListSet for a brief description of the split-list algorithm.
48
49         Template parameters:
50         - \p GC - Garbage collector used
51         - \p T - type to be stored in the split-list.
52         - \p Traits - type traits, default is \p split_list::traits. Instead of declaring \p split_list::traits -based
53             struct you may apply option-based notation with \p split_list::make_traits metafunction.
54
55         There are the specializations:
56         - for \ref cds_urcu_desc "RCU" - declared in <tt>cd/container/split_list_set_rcu.h</tt>,
57             see \ref cds_nonintrusive_SplitListSet_rcu "SplitListSet<RCU>".
58         - for \ref cds::gc::nogc declared in <tt>cds/container/split_list_set_nogc.h</tt>,
59             see \ref cds_nonintrusive_SplitListSet_nogc "SplitListSet<gc::nogc>".
60
61         \par Usage
62
63         You should decide what garbage collector you want, and what ordered list you want to use as a base. Split-ordered list
64         is original data structure based on an ordered list.
65
66         Suppose, you want construct split-list set based on \p gc::DHP GC
67         and \p LazyList as ordered list implementation. So, you beginning your program with following include:
68         \code
69         #include <cds/container/lazy_list_dhp.h>
70         #include <cds/container/split_list_set.h>
71
72         namespace cc = cds::container;
73
74         // The data belonged to split-ordered list
75         sturuct foo {
76             int     nKey;   // key field
77             std::string strValue    ;   // value field
78         };
79         \endcode
80         The inclusion order is important: first, include header for ordered-list implementation (for this example, <tt>cds/container/lazy_list_dhp.h</tt>),
81         then the header for split-list set <tt>cds/container/split_list_set.h</tt>.
82
83         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.
84         Note that we define several function in <tt>foo_hash</tt> and <tt>foo_less</tt> functors for different argument types since we want call our \p %SplitListSet
85         object by the key of type <tt>int</tt> and by the value of type <tt>foo</tt>.
86
87         The second attention: instead of using \p %LazyList in \p %SplitListSet traits we use a tag \p cds::contaner::lazy_list_tag for the lazy list.
88         The split-list requires significant support from underlying ordered list class and it is not good idea to dive you
89         into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface.
90
91         \code
92         // foo hash functor
93         struct foo_hash {
94             size_t operator()( int key ) const { return std::hash( key ) ; }
95             size_t operator()( foo const& item ) const { return std::hash( item.nKey ) ; }
96         };
97
98         // foo comparator
99         struct foo_less {
100             bool operator()(int i, foo const& f ) const { return i < f.nKey ; }
101             bool operator()(foo const& f, int i ) const { return f.nKey < i ; }
102             bool operator()(foo const& f1, foo const& f2) const { return f1.nKey < f2.nKey; }
103         };
104
105         // SplitListSet traits
106         struct foo_set_traits: public cc::split_list::traits
107         {
108             typedef cc::lazy_list_tag   ordered_list; // what type of ordered list we want to use
109             typedef foo_hash            hash;         // hash functor for our data stored in split-list set
110
111             // Type traits for our LazyList class
112             struct ordered_list_traits: public cc::lazy_list::traits
113             {
114                 typedef foo_less less   ;   // use our foo_less as comparator to order list nodes
115             };
116         };
117         \endcode
118
119         Now you are ready to declare our set class based on \p %SplitListSet:
120         \code
121         typedef cc::SplitListSet< cds::gc::DHP, foo, foo_set_traits > foo_set;
122         \endcode
123
124         You may use the modern option-based declaration instead of classic traits-based one:
125         \code
126         typedef cc::SplitListSet<
127             cs::gc::DHP             // GC used
128             ,foo                    // type of data stored
129             ,cc::split_list::make_traits<      // metafunction to build split-list traits
130                 cc::split_list::ordered_list<cc::lazy_list_tag>  // tag for underlying ordered list implementation
131                 ,cc::opt::hash< foo_hash >               // hash functor
132                 ,cc::split_list::ordered_list_traits<    // ordered list traits desired
133                     cc::lazy_list::make_traits<          // metafunction to build lazy list traits
134                         cc::opt::less< foo_less >        // less-based compare functor
135                     >::type
136                 >
137             >::type
138         >  foo_set;
139         \endcode
140         In case of option-based declaration using split_list::make_traits metafunction
141         the struct \p foo_set_traits is not required.
142
143         Now, the set of type \p foo_set is ready to use in your program.
144
145         Note that in this example we show only mandatory \p traits parts, optional ones is the default and they are inherited
146         from \p cds::container::split_list::traits.
147         There are many other options for deep tuning the split-list and ordered-list containers.
148     */
149     template <
150         class GC,
151         class T,
152 #ifdef CDS_DOXYGEN_INVOKED
153         class Traits = split_list::traits
154 #else
155         class Traits
156 #endif
157     >
158     class SplitListSet:
159 #ifdef CDS_DOXYGEN_INVOKED
160         protected intrusive::SplitListSet<GC, typename Traits::ordered_list, Traits>
161 #else
162         protected details::make_split_list_set< GC, T, typename Traits::ordered_list, split_list::details::wrap_set_traits<T, Traits> >::type
163 #endif
164     {
165     protected:
166         //@cond
167         typedef details::make_split_list_set< GC, T, typename Traits::ordered_list, split_list::details::wrap_set_traits<T, Traits> > maker;
168         typedef typename maker::type  base_class;
169         //@endcond
170
171     public:
172         typedef GC      gc;         ///< Garbage collector
173         typedef T       value_type; ///< Type of vlue to be stored in split-list
174         typedef Traits  traits;     ///< \p Traits template argument
175         typedef typename maker::ordered_list ordered_list; ///< Underlying ordered list class
176         typedef typename base_class::key_comparator key_comparator; ///< key compare functor
177
178         /// Hash functor for \p %value_type and all its derivatives that you use
179         typedef typename base_class::hash         hash;
180         typedef typename base_class::item_counter item_counter; ///< Item counter type
181         typedef typename base_class::stat         stat; ///< Internal statistics
182
183         /// Count of hazard pointer required
184         static CDS_CONSTEXPR const size_t c_nHazardPtrCount = base_class::c_nHazardPtrCount;
185
186     protected:
187         //@cond
188         typedef typename maker::cxx_node_allocator    cxx_node_allocator;
189         typedef typename maker::node_type             node_type;
190         //@endcond
191
192     public:
193         /// Guarded pointer
194         typedef typename gc::template guarded_ptr< node_type, value_type, details::guarded_ptr_cast_set<node_type, value_type> > guarded_ptr;
195
196     protected:
197         //@cond
198         template <typename Q>
199         static node_type * alloc_node(Q const& v )
200         {
201             return cxx_node_allocator().New( v );
202         }
203
204         template <typename... Args>
205         static node_type * alloc_node( Args&&... args )
206         {
207             return cxx_node_allocator().MoveNew( std::forward<Args>( args )... );
208         }
209
210         static void free_node( node_type * pNode )
211         {
212             cxx_node_allocator().Delete( pNode );
213         }
214
215         template <typename Q, typename Func>
216         bool find_( Q& val, Func f )
217         {
218             return base_class::find( val, [&f]( node_type& item, Q& val ) { f(item.m_Value, val) ; } );
219         }
220
221         template <typename Q, typename Less, typename Func>
222         bool find_with_( Q& val, Less pred, Func f )
223         {
224             CDS_UNUSED( pred );
225             return base_class::find_with( val, typename maker::template predicate_wrapper<Less>::type(),
226                 [&f]( node_type& item, Q& val ) { f(item.m_Value, val) ; } );
227         }
228
229         struct node_disposer {
230             void operator()( node_type * pNode )
231             {
232                 free_node( pNode );
233             }
234         };
235         typedef std::unique_ptr< node_type, node_disposer >     scoped_node_ptr;
236
237         bool insert_node( node_type * pNode )
238         {
239             assert( pNode != nullptr );
240             scoped_node_ptr p(pNode);
241
242             if ( base_class::insert( *pNode )) {
243                 p.release();
244                 return true;
245             }
246             return false;
247         }
248
249         //@endcond
250
251     protected:
252         //@cond
253         template <bool IsConst>
254         class iterator_type: protected base_class::template iterator_type<IsConst>
255         {
256             typedef typename base_class::template iterator_type<IsConst> iterator_base_class;
257             friend class SplitListSet;
258
259         public:
260             /// Value pointer type (const for const iterator)
261             typedef typename cds::details::make_const_type<value_type, IsConst>::pointer   value_ptr;
262             /// Value reference type (const for const iterator)
263             typedef typename cds::details::make_const_type<value_type, IsConst>::reference value_ref;
264
265         public:
266             /// Default ctor
267             iterator_type()
268             {}
269
270             /// Copy ctor
271             iterator_type( iterator_type const& src )
272                 : iterator_base_class( src )
273             {}
274
275         protected:
276             explicit iterator_type( iterator_base_class const& src )
277                 : iterator_base_class( src )
278             {}
279
280         public:
281             /// Dereference operator
282             value_ptr operator ->() const
283             {
284                 return &(iterator_base_class::operator->()->m_Value);
285             }
286
287             /// Dereference operator
288             value_ref operator *() const
289             {
290                 return iterator_base_class::operator*().m_Value;
291             }
292
293             /// Pre-increment
294             iterator_type& operator ++()
295             {
296                 iterator_base_class::operator++();
297                 return *this;
298             }
299
300             /// Assignment operator
301             iterator_type& operator = (iterator_type const& src)
302             {
303                 iterator_base_class::operator=(src);
304                 return *this;
305             }
306
307             /// Equality operator
308             template <bool C>
309             bool operator ==(iterator_type<C> const& i ) const
310             {
311                 return iterator_base_class::operator==(i);
312             }
313
314             /// Equality operator
315             template <bool C>
316             bool operator !=(iterator_type<C> const& i ) const
317             {
318                 return iterator_base_class::operator!=(i);
319             }
320         };
321         //@endcond
322
323     public:
324         /// Initializes split-ordered list of default capacity
325         /**
326             The default capacity is defined in bucket table constructor.
327             See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table
328             which selects by \p split_list::dynamic_bucket_table option.
329         */
330         SplitListSet()
331             : base_class()
332         {}
333
334         /// Initializes split-ordered list
335         SplitListSet(
336             size_t nItemCount           ///< estimated average of item count
337             , size_t nLoadFactor = 1    ///< the load factor - average item count per bucket. Small integer up to 8, default is 1.
338             )
339             : base_class( nItemCount, nLoadFactor )
340         {}
341
342     public:
343     ///@name Forward iterators (only for debugging purpose)
344     //@{
345         /// Forward iterator
346         /**
347             The forward iterator for a split-list has the following features:
348             - it has no post-increment operator
349             - it depends on underlying ordered list iterator
350             - The iterator object cannot be moved across thread boundary because it contains GC's guard that is thread-private GC data.
351             - Iterator ensures thread-safety even if you delete the item that iterator points to. However, in case of concurrent
352               deleting operations it is no guarantee that you iterate all item in the split-list.
353               Moreover, a crash is possible when you try to iterate the next element that has been deleted by concurrent thread.
354
355               @warning Use this iterator on the concurrent container for debugging purpose only.
356
357               The iterator interface:
358               \code
359               class iterator {
360               public:
361                   // Default constructor
362                   iterator();
363
364                   // Copy construtor
365                   iterator( iterator const& src );
366
367                   // Dereference operator
368                   value_type * operator ->() const;
369
370                   // Dereference operator
371                   value_type& operator *() const;
372
373                   // Preincrement operator
374                   iterator& operator ++();
375
376                   // Assignment operator
377                   iterator& operator = (iterator const& src);
378
379                   // Equality operators
380                   bool operator ==(iterator const& i ) const;
381                   bool operator !=(iterator const& i ) const;
382               };
383               \endcode
384         */
385         typedef iterator_type<false>  iterator;
386
387         /// Const forward iterator
388         typedef iterator_type<true>    const_iterator;
389
390         /// Returns a forward iterator addressing the first element in a set
391         /**
392             For empty set \code begin() == end() \endcode
393         */
394         iterator begin()
395         {
396             return iterator( base_class::begin());
397         }
398
399         /// Returns an iterator that addresses the location succeeding the last element in a set
400         /**
401             Do not use the value returned by <tt>end</tt> function to access any item.
402             The returned value can be used only to control reaching the end of the set.
403             For empty set \code begin() == end() \endcode
404         */
405         iterator end()
406         {
407             return iterator( base_class::end());
408         }
409
410         /// Returns a forward const iterator addressing the first element in a set
411         const_iterator begin() const
412         {
413             return cbegin();
414         }
415         /// Returns a forward const iterator addressing the first element in a set
416         const_iterator cbegin() const
417         {
418             return const_iterator( base_class::cbegin());
419         }
420
421         /// Returns an const iterator that addresses the location succeeding the last element in a set
422         const_iterator end() const
423         {
424             return cend();
425         }
426         /// Returns an const iterator that addresses the location succeeding the last element in a set
427         const_iterator cend() const
428         {
429             return const_iterator( base_class::cend());
430         }
431     //@}
432
433     public:
434         /// Inserts new node
435         /**
436             The function creates a node with copy of \p val value
437             and then inserts the node created into the set.
438
439             The type \p Q should contain as minimum the complete key for the node.
440             The object of \ref value_type should be constructible from a value of type \p Q.
441             In trivial case, \p Q is equal to \ref value_type.
442
443             Returns \p true if \p val is inserted into the set, \p false otherwise.
444         */
445         template <typename Q>
446         bool insert( Q const& val )
447         {
448             return insert_node( alloc_node( val ));
449         }
450
451         /// Inserts new node
452         /**
453             The function allows to split creating of new item into two part:
454             - create item with key only
455             - insert new item into the set
456             - if inserting is success, calls  \p f functor to initialize value-field of \p val.
457
458             The functor signature is:
459             \code
460                 void func( value_type& val );
461             \endcode
462             where \p val is the item inserted.
463
464             The user-defined functor is called only if the inserting is success.
465
466             @warning For \ref cds_intrusive_MichaelList_hp "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
467             \ref cds_intrusive_LazyList_hp "LazyList" provides exclusive access to inserted item and does not require any node-level
468             synchronization.
469         */
470         template <typename Q, typename Func>
471         bool insert( Q const& val, Func f )
472         {
473             scoped_node_ptr pNode( alloc_node( val ));
474
475             if ( base_class::insert( *pNode, [&f](node_type& node) { f( node.m_Value ) ; } )) {
476                 pNode.release();
477                 return true;
478             }
479             return false;
480         }
481
482         /// Inserts data of type \p value_type created from \p args
483         /**
484             Returns \p true if inserting successful, \p false otherwise.
485         */
486         template <typename... Args>
487         bool emplace( Args&&... args )
488         {
489             return insert_node( alloc_node( std::forward<Args>(args)...));
490         }
491
492         /// Updates the node
493         /**
494             The operation performs inserting or changing data with lock-free manner.
495
496             If \p key is not found in the set, then \p key is inserted iff \p bAllowInsert is \p true.
497             Otherwise, the functor \p func is called with item found.
498
499             The functor signature is:
500             \code
501                 struct my_functor {
502                     void operator()( bool bNew, value_type& item, const Q& val );
503                 };
504             \endcode
505             with arguments:
506             - \p bNew - \p true if the item has been inserted, \p false otherwise
507             - \p item - item of the set
508             - \p val - argument \p val passed into the \p %update() function
509
510             The functor may change non-key fields of the \p item.
511
512             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
513             \p second is true if new item has been added or \p false if the item with \p key
514             already is in the map.
515
516             @warning For \ref cds_intrusive_MichaelList_hp "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
517             \ref cds_intrusive_LazyList_hp "LazyList" provides exclusive access to inserted item and does not require any node-level
518             synchronization.
519         */
520         template <typename Q, typename Func>
521         std::pair<bool, bool> update( Q const& val, Func func, bool bAllowInsert = true )
522         {
523             scoped_node_ptr pNode( alloc_node( val ));
524
525             std::pair<bool, bool> bRet = base_class::update( *pNode,
526                 [&func, &val]( bool bNew, node_type& item,  node_type const& /*val*/ ) {
527                     func( bNew, item.m_Value, val );
528                 }, bAllowInsert );
529
530             if ( bRet.first && bRet.second )
531                 pNode.release();
532             return bRet;
533         }
534         //@cond
535         template <typename Q, typename Func>
536         CDS_DEPRECATED("ensure() is deprecated, use update()")
537         std::pair<bool, bool> ensure( Q const& val, Func func )
538         {
539             return update( val, func, true );
540         }
541         //@endcond
542
543         /// Deletes \p key from the set
544         /** \anchor cds_nonintrusive_SplitListSet_erase_val
545
546             The item comparator should be able to compare the values of type \p value_type
547             and the type \p Q.
548
549             Return \p true if key is found and deleted, \p false otherwise
550         */
551         template <typename Q>
552         bool erase( Q const& key )
553         {
554             return base_class::erase( key );
555         }
556
557         /// Deletes the item from the set using \p pred predicate for searching
558         /**
559             The function is an analog of \ref cds_nonintrusive_SplitListSet_erase_val "erase(Q const&)"
560             but \p pred is used for key comparing.
561             \p Less functor has the interface like \p std::less.
562             \p Less must imply the same element order as the comparator used for building the set.
563         */
564         template <typename Q, typename Less>
565         bool erase_with( Q const& key, Less pred )
566         {
567             CDS_UNUSED( pred );
568             return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type());
569         }
570
571         /// Deletes \p key from the set
572         /** \anchor cds_nonintrusive_SplitListSet_erase_func
573
574             The function searches an item with key \p key, calls \p f functor
575             and deletes the item. If \p key is not found, the functor is not called.
576
577             The functor \p Func interface:
578             \code
579             struct extractor {
580                 void operator()(value_type const& val);
581             };
582             \endcode
583
584             Since the key of split-list \p value_type is not explicitly specified,
585             template parameter \p Q defines the key type searching in the list.
586             The list item comparator should be able to compare the values of the type \p value_type
587             and the type \p Q.
588
589             Return \p true if key is found and deleted, \p false otherwise
590         */
591         template <typename Q, typename Func>
592         bool erase( Q const& key, Func f )
593         {
594             return base_class::erase( key, [&f](node_type& node) { f( node.m_Value ); } );
595         }
596
597         /// Deletes the item from the set using \p pred predicate for searching
598         /**
599             The function is an analog of \ref cds_nonintrusive_SplitListSet_erase_func "erase(Q const&, Func)"
600             but \p pred is used for key comparing.
601             \p Less functor has the interface like \p std::less.
602             \p Less must imply the same element order as the comparator used for building the set.
603         */
604         template <typename Q, typename Less, typename Func>
605         bool erase_with( Q const& key, Less pred, Func f )
606         {
607             CDS_UNUSED( pred );
608             return base_class::erase_with( key, typename maker::template predicate_wrapper<Less>::type(),
609                 [&f](node_type& node) { f( node.m_Value ); } );
610         }
611
612         /// Extracts the item with specified \p key
613         /** \anchor cds_nonintrusive_SplitListSet_hp_extract
614             The function searches an item with key equal to \p key,
615             unlinks it from the set, and returns it as \p guarded_ptr.
616             If \p key is not found the function returns an empty guarded pointer.
617
618             Note the compare functor should accept a parameter of type \p Q that may be not the same as \p value_type.
619
620             The extracted item is freed automatically when returned \p guarded_ptr object will be destroyed or released.
621             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
622
623             Usage:
624             \code
625             typedef cds::container::SplitListSet< your_template_args > splitlist_set;
626             splitlist_set theSet;
627             // ...
628             {
629                 splitlist_set::guarded_ptr gp(theSet.extract( 5 ));
630                 if ( gp ) {
631                     // Deal with gp
632                     // ...
633                 }
634                 // Destructor of gp releases internal HP guard
635             }
636             \endcode
637         */
638         template <typename Q>
639         guarded_ptr extract( Q const& key )
640         {
641             return extract_( key );
642         }
643
644         /// Extracts the item using compare functor \p pred
645         /**
646             The function is an analog of \ref cds_nonintrusive_SplitListSet_hp_extract "extract(Q const&)"
647             but \p pred predicate is used for key comparing.
648
649             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
650             in any order.
651             \p pred must imply the same element order as the comparator used for building the set.
652         */
653         template <typename Q, typename Less>
654         guarded_ptr extract_with( Q const& key, Less pred )
655         {
656             return extract_with_( key, pred );
657         }
658
659         /// Finds the key \p key
660         /** \anchor cds_nonintrusive_SplitListSet_find_func
661
662             The function searches the item with key equal to \p key and calls the functor \p f for item found.
663             The interface of \p Func functor is:
664             \code
665             struct functor {
666                 void operator()( value_type& item, Q& key );
667             };
668             \endcode
669             where \p item is the item found, \p key is the <tt>find</tt> function argument.
670
671             The functor may change non-key fields of \p item. Note that the functor is only guarantee
672             that \p item cannot be disposed during functor is executing.
673             The functor does not serialize simultaneous access to the set's \p item. If such access is
674             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
675
676             The \p key argument is non-const since it can be used as \p f functor destination i.e., the functor
677             may modify both arguments.
678
679             Note the hash functor specified for class \p Traits template parameter
680             should accept a parameter of type \p Q that can be not the same as \p value_type.
681
682             The function returns \p true if \p key is found, \p false otherwise.
683         */
684         template <typename Q, typename Func>
685         bool find( Q& key, Func f )
686         {
687             return find_( key, f );
688         }
689         //@cond
690         template <typename Q, typename Func>
691         bool find( Q const& key, Func f )
692         {
693             return find_( key, f );
694         }
695         //@endcond
696
697         /// Finds the key \p key using \p pred predicate for searching
698         /**
699             The function is an analog of \ref cds_nonintrusive_SplitListSet_find_func "find(Q&, Func)"
700             but \p pred is used for key comparing.
701             \p Less functor has the interface like \p std::less.
702             \p Less must imply the same element order as the comparator used for building the set.
703         */
704         template <typename Q, typename Less, typename Func>
705         bool find_with( Q& key, Less pred, Func f )
706         {
707             return find_with_( key, pred, f );
708         }
709         //@cond
710         template <typename Q, typename Less, typename Func>
711         bool find_with( Q const& key, Less pred, Func f )
712         {
713             return find_with_( key, pred, f );
714         }
715         //@endcond
716
717         /// Checks whether the set contains \p key
718         /**
719             The function searches the item with key equal to \p key
720             and returns \p true if it is found, and \p false otherwise.
721
722             Note the hash functor specified for class \p Traits template parameter
723             should accept a parameter of type \p Q that can be not the same as \p value_type.
724             Otherwise, you may use \p contains( Q const&, Less pred ) functions with explicit predicate for key comparing.
725         */
726         template <typename Q>
727         bool contains( Q const& key )
728         {
729             return base_class::contains( key );
730         }
731         //@cond
732         template <typename Q>
733         CDS_DEPRECATED("deprecated, use contains()")
734         bool find( Q const& key )
735         {
736             return contains( key );
737         }
738         //@endcond
739
740         /// Checks whether the map contains \p key using \p pred predicate for searching
741         /**
742             The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
743             \p Less functor has the interface like \p std::less.
744             \p Less must imply the same element order as the comparator used for building the map.
745         */
746         template <typename Q, typename Less>
747         bool contains( Q const& key, Less pred )
748         {
749             CDS_UNUSED( pred );
750             return base_class::contains( key, typename maker::template predicate_wrapper<Less>::type());
751         }
752         //@cond
753         template <typename Q, typename Less>
754         CDS_DEPRECATED("deprecated, use contains()")
755         bool find_with( Q const& key, Less pred )
756         {
757             return contains( key, pred );
758         }
759         //@endcond
760
761         /// Finds the key \p key and return the item found
762         /** \anchor cds_nonintrusive_SplitListSet_hp_get
763             The function searches the item with key equal to \p key
764             and returns the item found as \p guarded_ptr.
765             If \p key is not found the function returns an empty guarded pointer.
766
767             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
768
769             Usage:
770             \code
771             typedef cds::container::SplitListSet< your_template_params >  splitlist_set;
772             splitlist_set theSet;
773             // ...
774             {
775                 splitlist_set::guarded_ptr gp(theSet.get( 5 ));
776                 if ( gp ) {
777                     // Deal with gp
778                     //...
779                 }
780                 // Destructor of guarded_ptr releases internal HP guard
781             }
782             \endcode
783
784             Note the compare functor specified for split-list set
785             should accept a parameter of type \p Q that can be not the same as \p value_type.
786         */
787         template <typename Q>
788         guarded_ptr get( Q const& key )
789         {
790             return get_( key );
791         }
792
793         /// Finds \p key and return the item found
794         /**
795             The function is an analog of \ref cds_nonintrusive_SplitListSet_hp_get "get( Q const&)"
796             but \p pred is used for comparing the keys.
797
798             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
799             in any order.
800             \p pred must imply the same element order as the comparator used for building the set.
801         */
802         template <typename Q, typename Less>
803         guarded_ptr get_with( Q const& key, Less pred )
804         {
805             return get_with_( key, pred );
806         }
807
808         /// Clears the set (not atomic)
809         void clear()
810         {
811             base_class::clear();
812         }
813
814         /// Checks if the set is empty
815         /**
816             Emptiness is checked by item counting: if item count is zero then assume that the set is empty.
817             Thus, the correct item counting feature is an important part of split-list set implementation.
818         */
819         bool empty() const
820         {
821             return base_class::empty();
822         }
823
824         /// Returns item count in the set
825         size_t size() const
826         {
827             return base_class::size();
828         }
829
830         /// Returns internal statistics
831         stat const& statistics() const
832         {
833             return base_class::statistics();
834         }
835
836     protected:
837         //@cond
838         using base_class::extract_;
839         using base_class::get_;
840
841         template <typename Q, typename Less>
842         guarded_ptr extract_with_( Q const& key, Less pred )
843         {
844             CDS_UNUSED( pred );
845             return base_class::extract_with_( key, typename maker::template predicate_wrapper<Less>::type());
846         }
847
848         template <typename Q, typename Less>
849         guarded_ptr get_with_( Q const& key, Less pred )
850         {
851             CDS_UNUSED( pred );
852             return base_class::get_with_( key, typename maker::template predicate_wrapper<Less>::type());
853         }
854
855         //@endcond
856
857     };
858
859
860 }}  // namespace cds::container
861
862 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_SET_H