a1c83eda0ef95d240a0f41121e2551128f11eb01
[libcds.git] / cds / container / skip_list_map_impl.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_SKIP_LIST_MAP_IMPL_H
4 #define __CDS_CONTAINER_SKIP_LIST_MAP_IMPL_H
5
6 #include <cds/details/functor_wrapper.h>
7 #include <cds/gc/guarded_ptr.h>
8 #include <cds/container/details/guarded_ptr_cast.h>
9
10 namespace cds { namespace container {
11
12     /// Lock-free skip-list map
13     /** @ingroup cds_nonintrusive_map
14         \anchor cds_nonintrusive_SkipListMap_hp
15
16         The implementation of well-known probabilistic data structure called skip-list
17         invented by W.Pugh in his papers:
18             - [1989] W.Pugh Skip Lists: A Probabilistic Alternative to Balanced Trees
19             - [1990] W.Pugh A Skip List Cookbook
20
21         A skip-list is a probabilistic data structure that provides expected logarithmic
22         time search without the need of rebalance. The skip-list is a collection of sorted
23         linked list. Nodes are ordered by key. Each node is linked into a subset of the lists.
24         Each list has a level, ranging from 0 to 32. The bottom-level list contains
25         all the nodes, and each higher-level list is a sublist of the lower-level lists.
26         Each node is created with a random top level (with a random height), and belongs
27         to all lists up to that level. The probability that a node has the height 1 is 1/2.
28         The probability that a node has the height N is 1/2 ** N (more precisely,
29         the distribution depends on an random generator provided, but our generators
30         have this property).
31
32         The lock-free variant of skip-list is implemented according to book
33             - [2008] M.Herlihy, N.Shavit "The Art of Multiprocessor Programming",
34                 chapter 14.4 "A Lock-Free Concurrent Skiplist"
35
36         Template arguments:
37         - \p GC - Garbage collector used.
38         - \p K - type of a key to be stored in the list.
39         - \p T - type of a value to be stored in the list.
40         - \p Traits - type traits. See skip_list::type_traits for explanation.
41
42         It is possible to declare option-based list with cds::container::skip_list::make_traits metafunction istead of \p Traits template
43         argument.
44         Template argument list \p Options of cds::container::skip_list::make_traits metafunction are:
45         - opt::compare - key compare functor. No default functor is provided.
46             If the option is not specified, the opt::less is used.
47         - opt::less - specifies binary predicate used for key comparison. Default is \p std::less<K>.
48         - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter that is no item counting.
49         - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default)
50             or opt::v::sequential_consistent (sequentially consisnent memory model).
51         - skip_list::random_level_generator - random level generator. Can be skip_list::xorshift, skip_list::turbo_pascal or
52             user-provided one. See skip_list::random_level_generator option description for explanation.
53             Default is \p %skip_list::turbo_pascal.
54         - opt::allocator - allocator for skip-list node. Default is \ref CDS_DEFAULT_ALLOCATOR.
55         - opt::back_off - back-off strategy used. If the option is not specified, the cds::backoff::Default is used.
56         - opt::stat - internal statistics. Available types: skip_list::stat, skip_list::empty_stat (the default)
57
58         Like STL map class, %SkipListMap stores its key-value pair as <tt>std:pair< K const, T></tt>.
59
60         \warning The skip-list requires up to 67 hazard pointers that may be critical for some GCs for which
61             the guard count is limited (like as gc::HP, gc::HRC). Those GCs should be explicitly initialized with
62             hazard pointer enough: \code cds::gc::HP myhp( 67 ) \endcode. Otherwise an run-time exception may be raised
63             when you try to create skip-list object.
64
65         \note There are several specializations of \p %SkipListMap for each \p GC. You should include:
66         - <tt><cds/container/skip_list_map_hp.h></tt> for gc::HP garbage collector
67         - <tt><cds/container/skip_list_map_hrc.h></tt> for gc::HRC garbage collector
68         - <tt><cds/container/skip_list_map_ptb.h></tt> for gc::PTB garbage collector
69         - <tt><cds/container/skip_list_map_rcu.h></tt> for \ref cds_nonintrusive_SkipListMap_rcu "RCU type"
70         - <tt><cds/container/skip_list_map_nogc.h></tt> for \ref cds_nonintrusive_SkipListMap_nogc "non-deletable SkipListMap"
71
72         <b>Iterators</b>
73
74         The class supports a forward iterator (\ref iterator and \ref const_iterator).
75         The iteration is ordered.
76         The iterator object is thread-safe: the element pointed by the iterator object is guarded,
77         so, the element cannot be reclaimed while the iterator object is alive.
78         However, passing an iterator object between threads is dangerous.
79
80         \warning Due to concurrent nature of skip-list map it is not guarantee that you can iterate
81         all elements in the map: any concurrent deletion can exclude the element
82         pointed by the iterator from the map, and your iteration can be terminated
83         before end of the map. Therefore, such iteration is more suitable for debugging purpose only
84
85         Remember, each iterator object requires 2 additional hazard pointers, that may be
86         a limited resource for \p GC like as gc::HP and gc::HRC (however, for gc::PTB the count of
87         guards is unlimited).
88
89         The iterator class supports the following minimalistic interface:
90         \code
91         struct iterator {
92             // Default ctor
93             iterator();
94
95             // Copy ctor
96             iterator( iterator const& s);
97
98             value_type * operator ->() const;
99             value_type& operator *() const;
100
101             // Pre-increment
102             iterator& operator ++();
103
104             // Copy assignment
105             iterator& operator = (const iterator& src);
106
107             bool operator ==(iterator const& i ) const;
108             bool operator !=(iterator const& i ) const;
109         };
110         \endcode
111         Note, the iterator object returned by \ref end, \ cend member functions points to \p NULL and should not be dereferenced.
112
113     */
114     template <
115         typename GC,
116         typename Key,
117         typename T,
118 #ifdef CDS_DOXYGEN_INVOKED
119         typename Traits = skip_list::type_traits
120 #else
121         typename Traits
122 #endif
123     >
124     class SkipListMap:
125 #ifdef CDS_DOXYGEN_INVOKED
126         protected intrusive::SkipListSet< GC, std::pair<Key const, T>, Traits >
127 #else
128         protected details::make_skip_list_map< GC, Key, T, Traits >::type
129 #endif
130     {
131         //@cond
132         typedef details::make_skip_list_map< GC, Key, T, Traits >    maker;
133         typedef typename maker::type base_class;
134         //@endcond
135     public:
136         typedef typename base_class::gc          gc  ; ///< Garbage collector used
137         typedef Key     key_type    ;   ///< Key type
138         typedef T       mapped_type ;   ///< Mapped type
139 #   ifdef CDS_DOXYGEN_INVOKED
140         typedef std::pair< K const, T> value_type   ;   ///< Value type stored in the map
141 #   else
142         typedef typename maker::value_type  value_type;
143 #   endif
144         typedef Traits  options     ;   ///< Options specified
145
146         typedef typename base_class::back_off       back_off        ;   ///< Back-off strategy used
147         typedef typename options::allocator         allocator_type  ;   ///< Allocator type used for allocate/deallocate the skip-list nodes
148         typedef typename base_class::item_counter   item_counter    ;   ///< Item counting policy used
149         typedef typename maker::key_comparator      key_comparator  ;   ///< key comparison functor
150         typedef typename base_class::memory_model   memory_model    ;   ///< Memory ordering. See cds::opt::memory_model option
151         typedef typename options::random_level_generator random_level_generator ; ///< random level generator
152         typedef typename options::stat              stat            ;   ///< internal statistics type
153
154     protected:
155         //@cond
156         typedef typename maker::node_type           node_type;
157         typedef typename maker::node_allocator      node_allocator;
158
159         typedef std::unique_ptr< node_type, typename maker::node_deallocator >    scoped_node_ptr;
160
161         //@endcond
162
163     public:
164         /// Guarded pointer
165         typedef cds::gc::guarded_ptr< gc, node_type, value_type, details::guarded_ptr_cast_set<node_type, value_type> > guarded_ptr;
166
167     protected:
168         //@cond
169         unsigned int random_level()
170         {
171             return base_class::random_level();
172         }
173         //@endcond
174
175     protected:
176         //@cond
177 #   ifndef CDS_CXX11_LAMBDA_SUPPORT
178         struct empty_insert_functor
179         {
180             void operator()( value_type& ) const
181             {}
182         };
183
184         template <typename Q>
185         class insert_value_functor
186         {
187             Q const&    m_val;
188         public:
189             insert_value_functor( Q const & v)
190                 : m_val(v)
191             {}
192
193             void operator()( value_type& item )
194             {
195                 item.second = m_val;
196             }
197         };
198
199         template <typename Func>
200         class insert_key_wrapper: protected cds::details::functor_wrapper<Func>
201         {
202             typedef cds::details::functor_wrapper<Func> base_class;
203         public:
204             insert_key_wrapper( Func f ): base_class(f) {}
205
206             void operator()( node_type& item )
207             {
208                 base_class::get()( item.m_Value );
209             }
210         };
211
212         template <typename Func>
213         class ensure_wrapper: protected cds::details::functor_wrapper<Func>
214         {
215             typedef cds::details::functor_wrapper<Func> base_class;
216         public:
217             ensure_wrapper( Func f) : base_class(f) {}
218
219             void operator()( bool bNew, node_type& item, node_type const& )
220             {
221                 base_class::get()( bNew, item.m_Value );
222             }
223         };
224
225         template <typename Func>
226         struct erase_functor
227         {
228             Func        m_func;
229
230             erase_functor( Func f )
231                 : m_func(f)
232             {}
233
234             void operator()( node_type& node )
235             {
236                 cds::unref(m_func)( node.m_Value );
237             }
238         };
239
240         template <typename Func>
241         class find_wrapper: protected cds::details::functor_wrapper<Func>
242         {
243             typedef cds::details::functor_wrapper<Func> base_class;
244         public:
245             find_wrapper( Func f )
246                 : base_class(f)
247             {}
248
249             template <typename Q>
250             void operator()( node_type& item, Q& val )
251             {
252                 base_class::get()( item.m_Value, val );
253             }
254         };
255 #   endif  // #ifndef CDS_CXX11_LAMBDA_SUPPORT
256         //@endcond
257
258     public:
259         /// Default ctor
260         SkipListMap()
261             : base_class()
262         {}
263
264         /// Destructor destroys the set object
265         ~SkipListMap()
266         {}
267
268     public:
269         /// Iterator type
270         typedef skip_list::details::iterator< typename base_class::iterator >  iterator;
271
272         /// Const iterator type
273         typedef skip_list::details::iterator< typename base_class::const_iterator >   const_iterator;
274
275         /// Returns a forward iterator addressing the first element in a map
276         iterator begin()
277         {
278             return iterator( base_class::begin() );
279         }
280
281         /// Returns a forward const iterator addressing the first element in a map
282         //@{
283         const_iterator begin() const
284         {
285             return cbegin();
286         }
287         const_iterator cbegin()
288         {
289             return const_iterator( base_class::cbegin() );
290         }
291         //@}
292
293         /// Returns a forward iterator that addresses the location succeeding the last element in a map.
294         iterator end()
295         {
296             return iterator( base_class::end() );
297         }
298
299         /// Returns a forward const iterator that addresses the location succeeding the last element in a map.
300         //@{
301         const_iterator end() const
302         {
303             return cend();
304         }
305         const_iterator cend()
306         {
307             return const_iterator( base_class::cend() );
308         }
309         //@}
310
311     public:
312         /// Inserts new node with key and default value
313         /**
314             The function creates a node with \p key and default value, and then inserts the node created into the map.
315
316             Preconditions:
317             - The \ref key_type should be constructible from a value of type \p K.
318                 In trivial case, \p K is equal to \ref key_type.
319             - The \ref mapped_type should be default-constructible.
320
321             Returns \p true if inserting successful, \p false otherwise.
322         */
323         template <typename K>
324         bool insert( K const& key )
325         {
326 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
327             return insert_key( key, [](value_type&){} );
328 #       else
329             return insert_key( key, empty_insert_functor() );
330 #       endif
331         }
332
333         /// Inserts new node
334         /**
335             The function creates a node with copy of \p val value
336             and then inserts the node created into the map.
337
338             Preconditions:
339             - The \ref key_type should be constructible from \p key of type \p K.
340             - The \ref value_type should be constructible from \p val of type \p V.
341
342             Returns \p true if \p val is inserted into the set, \p false otherwise.
343         */
344         template <typename K, typename V>
345         bool insert( K const& key, V const& val )
346         {
347 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
348             return insert_key( key, [&val](value_type& item) { item.second = val ; } );
349 #       else
350             insert_value_functor<V> f(val);
351             return insert_key( key, cds::ref(f) );
352 #       endif
353         }
354
355         /// Inserts new node and initialize it by a functor
356         /**
357             This function inserts new node with key \p key and if inserting is successful then it calls
358             \p func functor with signature
359             \code
360                 struct functor {
361                     void operator()( value_type& item );
362                 };
363             \endcode
364
365             The argument \p item of user-defined functor \p func is the reference
366             to the map's item inserted:
367                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
368                 - <tt>item.second</tt> is a reference to item's value that may be changed.
369
370             The user-defined functor can be passed by reference using <tt>boost::ref</tt>
371             and it is called only if inserting is successful.
372
373             The key_type should be constructible from value of type \p K.
374
375             The function allows to split creating of new item into two part:
376             - create item from \p key;
377             - insert new item into the map;
378             - if inserting is successful, initialize the value of item by calling \p func functor
379
380             This can be useful if complete initialization of object of \p value_type is heavyweight and
381             it is preferable that the initialization should be completed only if inserting is successful.
382         */
383         template <typename K, typename Func>
384         bool insert_key( const K& key, Func func )
385         {
386             scoped_node_ptr pNode( node_allocator().New( random_level(), key ));
387 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
388             if ( base_class::insert( *pNode, [&func]( node_type& item ) { cds::unref(func)( item.m_Value ); } ))
389 #       else
390             insert_key_wrapper<Func> wrapper(func);
391             if ( base_class::insert( *pNode, cds::ref(wrapper) ))
392 #endif
393             {
394                 pNode.release();
395                 return true;
396             }
397             return false;
398         }
399
400 #   ifdef CDS_EMPLACE_SUPPORT
401         /// For key \p key inserts data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt>
402         /**
403             Returns \p true if inserting successful, \p false otherwise.
404
405             @note This function is available only for compiler that supports
406             variadic template and move semantics
407         */
408         template <typename K, typename... Args>
409         bool emplace( K&& key, Args&&... args )
410         {
411             scoped_node_ptr pNode( node_allocator().New( random_level(), std::forward<K>(key), std::forward<Args>(args)... ));
412             if ( base_class::insert( *pNode )) {
413                 pNode.release();
414                 return true;
415             }
416             return false;
417         }
418 #   endif
419
420
421         /// Ensures that the \p key exists in the map
422         /**
423             The operation performs inserting or changing data with lock-free manner.
424
425             If the \p key not found in the map, then the new item created from \p key
426             is inserted into the map (note that in this case the \ref key_type should be
427             constructible from type \p K).
428             Otherwise, the functor \p func is called with item found.
429             The functor \p Func may be a function with signature:
430             \code
431                 void func( bool bNew, value_type& item );
432             \endcode
433             or a functor:
434             \code
435                 struct my_functor {
436                     void operator()( bool bNew, value_type& item );
437                 };
438             \endcode
439
440             with arguments:
441             - \p bNew - \p true if the item has been inserted, \p false otherwise
442             - \p item - item of the list
443
444             The functor may change any fields of the \p item.second that is \ref value_type.
445
446             You may pass \p func argument by reference using <tt>boost::ref</tt>.
447
448             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
449             \p second is true if new item has been added or \p false if the item with \p key
450             already is in the list.
451         */
452         template <typename K, typename Func>
453         std::pair<bool, bool> ensure( K const& key, Func func )
454         {
455             scoped_node_ptr pNode( node_allocator().New( random_level(), key ));
456 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
457             std::pair<bool, bool> res = base_class::ensure( *pNode,
458                 [&func](bool bNew, node_type& item, node_type const& ){ cds::unref(func)( bNew, item.m_Value ); }
459             );
460 #       else
461             ensure_wrapper<Func> wrapper( func );
462             std::pair<bool, bool> res = base_class::ensure( *pNode, cds::ref(wrapper) );
463 #       endif
464             if ( res.first && res.second )
465                 pNode.release();
466             return res;
467         }
468
469         /// Delete \p key from the map
470         /** \anchor cds_nonintrusive_SkipListMap_erase_val
471
472             Return \p true if \p key is found and deleted, \p false otherwise
473         */
474         template <typename K>
475         bool erase( K const& key )
476         {
477             return base_class::erase(key);
478         }
479
480         /// Deletes the item from the map using \p pred predicate for searching
481         /**
482             The function is an analog of \ref cds_nonintrusive_SkipListMap_erase_val "erase(K const&)"
483             but \p pred is used for key comparing.
484             \p Less functor has the interface like \p std::less.
485             \p Less must imply the same element order as the comparator used for building the map.
486         */
487         template <typename K, typename Less>
488         bool erase_with( K const& key, Less pred )
489         {
490             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >());
491         }
492
493         /// Delete \p key from the map
494         /** \anchor cds_nonintrusive_SkipListMap_erase_func
495
496             The function searches an item with key \p key, calls \p f functor
497             and deletes the item. If \p key is not found, the functor is not called.
498
499             The functor \p Func interface:
500             \code
501             struct extractor {
502                 void operator()(value_type& item) { ... }
503             };
504             \endcode
505             The functor may be passed by reference using <tt>boost:ref</tt>
506
507             Return \p true if key is found and deleted, \p false otherwise
508         */
509         template <typename K, typename Func>
510         bool erase( K const& key, Func f )
511         {
512 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
513             return base_class::erase( key, [&f]( node_type& node) { cds::unref(f)( node.m_Value ); } );
514 #       else
515             erase_functor<Func> wrapper(f);
516             return base_class::erase( key, cds::ref(wrapper));
517 #       endif
518         }
519
520         /// Deletes the item from the map using \p pred predicate for searching
521         /**
522             The function is an analog of \ref cds_nonintrusive_SkipListMap_erase_func "erase(K const&, Func)"
523             but \p pred is used for key comparing.
524             \p Less functor has the interface like \p std::less.
525             \p Less must imply the same element order as the comparator used for building the map.
526         */
527         template <typename K, typename Less, typename Func>
528         bool erase_with( K const& key, Less pred, Func f )
529         {
530 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
531             return base_class::erase_with( key,
532                 cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(),
533                 [&f]( node_type& node) { cds::unref(f)( node.m_Value ); } );
534 #       else
535             erase_functor<Func> wrapper(f);
536             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(), cds::ref(wrapper));
537 #       endif
538         }
539
540         /// Extracts the item from the map with specified \p key
541         /** \anchor cds_nonintrusive_SkipListMap_hp_extract
542             The function searches an item with key equal to \p key in the map,
543             unlinks it from the map, and returns it in \p ptr parameter.
544             If the item with key equal to \p key is not found the function returns \p false.
545
546             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
547
548             The item extracted is freed automatically by garbage collector \p GC
549             when returned \ref guarded_ptr object will be destroyed or released.
550             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
551
552             Usage:
553             \code
554             typedef cds::container::SkipListMap< cds::gc::HP, int, foo, my_traits >  skip_list;
555             skip_list theList;
556             // ...
557             {
558                 skip_list::guarded_ptr gp;
559                 if ( theList.extract( gp, 5 ) ) {
560                     // Deal with gp
561                     // ...
562                 }
563                 // Destructor of gp releases internal HP guard and frees the pointer
564             }
565             \endcode
566         */
567         template <typename K>
568         bool extract( guarded_ptr& ptr, K const& key )
569         {
570             return base_class::extract_( ptr.guard(), key, typename base_class::key_comparator() );
571         }
572
573         /// Extracts the item from the map with comparing functor \p pred
574         /**
575             The function is an analog of \ref cds_nonintrusive_SkipListMap_hp_extract "extract(K const&)"
576             but \p pred predicate is used for key comparing.
577
578             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
579             in any order.
580             \p pred must imply the same element order as the comparator used for building the map.
581         */
582         template <typename K, typename Less>
583         bool extract_with( guarded_ptr& ptr, K const& key, Less pred )
584         {
585             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >  wrapped_less;
586             return base_class::extract_( ptr.guard(), key, cds::opt::details::make_comparator_from_less<wrapped_less>() );
587         }
588
589         /// Extracts an item with minimal key from the map
590         /**
591             The function searches an item with minimal key, unlinks it, and returns the item found in \p ptr parameter.
592             If the skip-list is empty the function returns \p false.
593
594             The item extracted is freed automatically by garbage collector \p GC
595             when returned \ref guarded_ptr object will be destroyed or released.
596             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
597
598             Usage:
599             \code
600             typedef cds::continer::SkipListMap< cds::gc::HP, int, foo, my_traits >  skip_list;
601             skip_list theList;
602             // ...
603             {
604                 skip_list::guarded_ptr gp;
605                 if ( theList.extract_min( gp )) {
606                     // Deal with gp
607                     //...
608                 }
609                 // Destructor of gp releases internal HP guard and then frees the pointer
610             }
611             \endcode
612         */
613         bool extract_min( guarded_ptr& ptr)
614         {
615             return base_class::extract_min_( ptr.guard() );
616         }
617
618         /// Extracts an item with maximal key from the map
619         /**
620             The function searches an item with maximal key, unlinks it, and returns the pointer to item found in \p ptr parameter.
621             If the skip-list is empty the function returns empty \p guarded_ptr.
622
623             The item found is freed by garbage collector \p GC automatically
624             when returned \ref guarded_ptr object will be destroyed or released.
625             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
626
627             Usage:
628             \code
629             typedef cds::container::SkipListMap< cds::gc::HP, int, foo, my_traits >  skip_list;
630             skip_list theList;
631             // ...
632             {
633                 skip_list::guarded_ptr gp;
634                 if ( theList.extract_max( gp )) {
635                     // Deal with gp
636                     //...
637                 }
638                 // Destructor of gp releases internal HP guard and then frees the pointer
639             }
640             \endcode
641         */
642         bool extract_max( guarded_ptr& dest )
643         {
644             return base_class::extract_max_( dest.guard() );
645         }
646
647         /// Find the key \p key
648         /** \anchor cds_nonintrusive_SkipListMap_find_cfunc
649
650             The function searches the item with key equal to \p key and calls the functor \p f for item found.
651             The interface of \p Func functor is:
652             \code
653             struct functor {
654                 void operator()( value_type& item );
655             };
656             \endcode
657             where \p item is the item found.
658
659             You can pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
660
661             The functor may change \p item.second.
662
663             The function returns \p true if \p key is found, \p false otherwise.
664         */
665         template <typename K, typename Func>
666         bool find( K const& key, Func f )
667         {
668 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
669             return base_class::find( key, [&f](node_type& item, K const& ) { cds::unref(f)( item.m_Value );});
670 #       else
671             find_wrapper<Func> wrapper(f);
672             return base_class::find( key, cds::ref(wrapper) );
673 #       endif
674         }
675
676         /// Finds the key \p val using \p pred predicate for searching
677         /**
678             The function is an analog of \ref cds_nonintrusive_SkipListMap_find_cfunc "find(K const&, Func)"
679             but \p pred is used for key comparing.
680             \p Less functor has the interface like \p std::less.
681             \p Less must imply the same element order as the comparator used for building the map.
682         */
683         template <typename K, typename Less, typename Func>
684         bool find_with( K const& key, Less pred, Func f )
685         {
686 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
687             return base_class::find_with( key,
688                 cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(),
689                 [&f](node_type& item, K const& ) { cds::unref(f)( item.m_Value );});
690 #       else
691             find_wrapper<Func> wrapper(f);
692             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(), cds::ref(wrapper) );
693 #       endif
694         }
695
696         /// Find the key \p key
697         /** \anchor cds_nonintrusive_SkipListMap_find_val
698
699             The function searches the item with key equal to \p key
700             and returns \p true if it is found, and \p false otherwise.
701         */
702         template <typename K>
703         bool find( K const& key )
704         {
705             return base_class::find( key );
706         }
707
708         /// Finds the key \p val using \p pred predicate for searching
709         /**
710             The function is an analog of \ref cds_nonintrusive_SkipListMap_find_val "find(K const&)"
711             but \p pred is used for key comparing.
712             \p Less functor has the interface like \p std::less.
713             \p Less must imply the same element order as the comparator used for building the map.
714         */
715         template <typename K, typename Less>
716         bool find_with( K const& key, Less pred )
717         {
718             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >() );
719         }
720
721         /// Finds the key \p key and return the item found
722         /** \anchor cds_nonintrusive_SkipListMap_hp_get
723             The function searches the item with key equal to \p key
724             and assigns the item found to guarded pointer \p ptr.
725             The function returns \p true if \p key is found, and \p false otherwise.
726             If \p key is not found the \p ptr parameter is not changed.
727
728             It is safe when a concurrent thread erases the item returned in \p ptr guarded pointer.
729             In this case the item will be freed later by garbage collector \p GC automatically
730             when \p guarded_ptr object will be destroyed or released.
731             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
732
733             Usage:
734             \code
735             typedef cds::container::SkipListMap< cds::gc::HP, int, foo, my_traits >  skip_list;
736             skip_list theList;
737             // ...
738             {
739                 skip_list::guarded_ptr gp;
740                 if ( theList.get( gp, 5 ) ) {
741                     // Deal with gp
742                     //...
743                 }
744                 // Destructor of guarded_ptr releases internal HP guard
745             }
746             \endcode
747
748             Note the compare functor specified for class \p Traits template parameter
749             should accept a parameter of type \p K that can be not the same as \p value_type.
750         */
751         template <typename K>
752         bool get( guarded_ptr& ptr, K const& key )
753         {
754             return base_class::get_with_( ptr.guard(), key, typename base_class::key_comparator() );
755         }
756
757         /// Finds the key \p key and return the item found
758         /**
759             The function is an analog of \ref cds_nonintrusive_SkipListMap_hp_get "get( guarded_ptr& ptr, K const&)"
760             but \p pred is used for comparing the keys.
761
762             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
763             in any order.
764             \p pred must imply the same element order as the comparator used for building the map.
765         */
766         template <typename K, typename Less>
767         bool get_with( guarded_ptr& ptr, K const& key, Less pred )
768         {
769             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor > wrapped_less;
770             return base_class::get_with_( ptr.guard(), key, cds::opt::details::make_comparator_from_less< wrapped_less >());
771         }
772
773         /// Clears the map
774         void clear()
775         {
776             base_class::clear();
777         }
778
779         /// Checks if the map is empty
780         /**
781             Emptiness is checked by item counting: if item count is zero then the map is empty.
782         */
783         bool empty() const
784         {
785             return base_class::empty();
786         }
787
788         /// Returns item count in the map
789         size_t size() const
790         {
791             return base_class::size();
792         }
793
794         /// Returns const reference to internal statistics
795         stat const& statistics() const
796         {
797             return base_class::statistics();
798         }
799
800     };
801 }} // namespace cds::container
802
803 #endif // #ifndef __CDS_CONTAINER_SKIP_LIST_MAP_IMPL_H