02cd37fc04acddc410e69d94cc839493a7b6d4e4
[libcds.git] / cds / container / michael_kvlist_impl.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_MICHAEL_KVLIST_IMPL_H
4 #define __CDS_CONTAINER_MICHAEL_KVLIST_IMPL_H
5
6 #include <cds/ref.h>
7 #include <cds/details/functor_wrapper.h>
8 #include <cds/details/std/memory.h>
9 #include <cds/container/details/guarded_ptr_cast.h>
10
11 namespace cds { namespace container {
12
13     /// Michael's ordered list (key-value pair)
14     /** @ingroup cds_nonintrusive_list
15         \anchor cds_nonintrusive_MichaelKVList_gc
16
17         This is key-value variation of non-intrusive MichaelList.
18         Like standard container, this implementation split a value stored into two part -
19         constant key and alterable value.
20
21         Usually, ordered single-linked list is used as a building block for the hash table implementation.
22         The complexity of searching is <tt>O(N)</tt>.
23
24         Template arguments:
25         - \p GC - garbage collector used
26         - \p Key - key type of an item stored in the list. It should be copy-constructible
27         - \p Value - value type stored in a list
28         - \p Traits - type traits, default is michael_list::type_traits
29
30         It is possible to declare option-based list with cds::container::michael_list::make_traits metafunction istead of \p Traits template
31         argument. For example, the following traits-based declaration of gc::HP Michael's list
32         \code
33         #include <cds/container/michael_kvlist_hp.h>
34         // Declare comparator for the item
35         struct my_compare {
36             int operator ()( int i1, int i2 )
37             {
38                 return i1 - i2;
39             }
40         };
41
42         // Declare type_traits
43         struct my_traits: public cds::container::michael_list::type_traits
44         {
45             typedef my_compare compare;
46         };
47
48         // Declare traits-based list
49         typedef cds::container::MichaelKVList< cds::gc::HP, int, int, my_traits >     traits_based_list;
50         \endcode
51
52         is equivalent for the following option-based list
53         \code
54         #include <cds/container/michael_kvlist_hp.h>
55
56         // my_compare is the same
57
58         // Declare option-based list
59         typedef cds::container::MichaelKVList< cds::gc::HP, int, int,
60             typename cds::container::michael_list::make_traits<
61                 cds::container::opt::compare< my_compare >     // item comparator option
62             >::type
63         >     option_based_list;
64         \endcode
65
66         Template argument list \p Options of cds::container::michael_list::make_traits metafunction are:
67         - opt::compare - key comparison functor. No default functor is provided.
68             If the option is not specified, the opt::less is used.
69         - opt::less - specifies binary predicate used for key comparison. Default is \p std::less<T>.
70         - opt::back_off - back-off strategy used. If the option is not specified, the cds::backoff::empty is used.
71         - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter that is no item counting.
72         - opt::allocator - the allocator used for creating and freeing list's item. Default is \ref CDS_DEFAULT_ALLOCATOR macro.
73         - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default)
74             or opt::v::sequential_consistent (sequentially consisnent memory model).
75
76         \par Usage
77         There are different specializations of this template for each garbage collecting schema used.
78         You should include appropriate .h-file depending on GC you are using:
79         - for gc::HP: \code #include <cds/container/michael_kvlist_hp.h> \endcode
80         - for gc::PTB: \code #include <cds/container/michael_kvlist_ptb.h> \endcode
81         - for gc::HRC: \code #include <cds/container/michael_kvlist_hrc.h> \endcode
82         - for \ref cds_urcu_desc "RCU": \code #include <cds/container/michael_kvlist_rcu.h> \endcode
83         - for gc::nogc: \code #include <cds/container/michael_kvlist_nogc.h> \endcode
84     */
85     template <
86         typename GC,
87         typename Key,
88         typename Value,
89 #ifdef CDS_DOXYGEN_INVOKED
90         typename Traits = michael_list::type_traits
91 #else
92         typename Traits
93 #endif
94     >
95     class MichaelKVList:
96 #ifdef CDS_DOXYGEN_INVOKED
97         protected intrusive::MichaelList< GC, implementation_defined, Traits >
98 #else
99         protected details::make_michael_kvlist< GC, Key, Value, Traits >::type
100 #endif
101     {
102         //@cond
103         typedef details::make_michael_kvlist< GC, Key, Value, Traits > options;
104         typedef typename options::type  base_class;
105         //@endcond
106
107     public:
108 #ifdef CDS_DOXYGEN_INVOKED
109         typedef Key                                 key_type        ;   ///< Key type
110         typedef Value                               mapped_type     ;   ///< Type of value stored in the list
111         typedef std::pair<key_type const, mapped_type> value_type   ;   ///< key/value pair stored in the list
112 #else
113         typedef typename options::key_type          key_type;
114         typedef typename options::value_type        mapped_type;
115         typedef typename options::pair_type         value_type;
116 #endif
117
118         typedef typename base_class::gc             gc              ;   ///< Garbage collector used
119         typedef typename base_class::back_off       back_off        ;   ///< Back-off strategy used
120         typedef typename options::allocator_type    allocator_type  ;   ///< Allocator type used for allocate/deallocate the nodes
121         typedef typename base_class::item_counter   item_counter    ;   ///< Item counting policy used
122         typedef typename options::key_comparator    key_comparator  ;   ///< key comparison functor
123         typedef typename base_class::memory_model   memory_model    ;   ///< Memory ordering. See cds::opt::memory_model option
124
125     protected:
126         //@cond
127         typedef typename base_class::value_type     node_type;
128         typedef typename options::cxx_allocator     cxx_allocator;
129         typedef typename options::node_deallocator  node_deallocator;
130         typedef typename options::type_traits::compare  intrusive_key_comparator;
131
132         typedef typename base_class::atomic_node_ptr head_type;
133         //@endcond
134
135     public:
136         /// Guarded pointer
137         typedef cds::gc::guarded_ptr< gc, node_type, value_type, details::guarded_ptr_cast_map<node_type, value_type> > guarded_ptr;
138
139     private:
140         //@cond
141 #   ifndef CDS_CXX11_LAMBDA_SUPPORT
142         template <typename Func>
143         class insert_functor: protected cds::details::functor_wrapper<Func>
144         {
145             typedef cds::details::functor_wrapper<Func> base_class;
146         public:
147             insert_functor ( Func f )
148                 : base_class( f )
149             {}
150
151             void operator()( node_type& node )
152             {
153                 base_class::get()( node.m_Data );
154             }
155         };
156
157         template <typename Func>
158         class ensure_functor: protected cds::details::functor_wrapper<Func>
159         {
160             typedef cds::details::functor_wrapper<Func> base_class;
161         public:
162             ensure_functor( Func f )
163                 : base_class(f)
164             {}
165
166             void operator ()( bool bNew, node_type& node, node_type& )
167             {
168                 base_class::get()( bNew, node.m_Data );
169             }
170         };
171
172         template <typename Func>
173         class find_functor: protected cds::details::functor_wrapper<Func>
174         {
175             typedef cds::details::functor_wrapper<Func> base_class;
176         public:
177             find_functor( Func f )
178                 : base_class(f)
179             {}
180
181             template <typename Q>
182             void operator ()( node_type& node, Q&  )
183             {
184                 base_class::get()( node.m_Data );
185             }
186         };
187
188         template <typename Func>
189         struct erase_functor
190         {
191             Func m_func;
192
193             erase_functor( Func f )
194                 : m_func( f )
195             {}
196
197             void operator ()( node_type const & node )
198             {
199                 cds::unref(m_func)( const_cast<value_type&>(node.m_Data) );
200             }
201         };
202 #   endif // ifndef CDS_CXX11_LAMBDA_SUPPORT
203         //@endcond
204
205     protected:
206         //@cond
207         template <typename K>
208         static node_type * alloc_node(const K& key)
209         {
210             return cxx_allocator().New( key );
211         }
212
213         template <typename K, typename V>
214         static node_type * alloc_node( const K& key, const V& val )
215         {
216             return cxx_allocator().New( key, val );
217         }
218
219 #   ifdef CDS_EMPLACE_SUPPORT
220         template <typename K, typename... Args>
221         static node_type * alloc_node( K&& key, Args&&... args )
222         {
223             return cxx_allocator().MoveNew( std::forward<K>(key), std::forward<Args>(args)...);
224         }
225 #   endif
226
227         static void free_node( node_type * pNode )
228         {
229             cxx_allocator().Delete( pNode );
230         }
231
232         struct node_disposer {
233             void operator()( node_type * pNode )
234             {
235                 free_node( pNode );
236             }
237         };
238         typedef std::unique_ptr< node_type, node_disposer >     scoped_node_ptr;
239
240         head_type& head()
241         {
242             return base_class::m_pHead;
243         }
244
245         head_type const& head() const
246         {
247             return base_class::m_pHead;
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;
257
258             iterator_type( head_type const& pNode )
259                 : iterator_base( pNode )
260             {}
261
262             friend class MichaelKVList;
263
264         public:
265             typedef typename cds::details::make_const_type<mapped_type, IsConst>::reference  value_ref;
266             typedef typename cds::details::make_const_type<mapped_type, IsConst>::pointer    value_ptr;
267
268             typedef typename cds::details::make_const_type<value_type,  IsConst>::reference  pair_ref;
269             typedef typename cds::details::make_const_type<value_type,  IsConst>::pointer    pair_ptr;
270
271             iterator_type()
272             {}
273
274             iterator_type( iterator_type const& src )
275                 : iterator_base( src )
276             {}
277
278             key_type const& key() const
279             {
280                 typename iterator_base::value_ptr p = iterator_base::operator ->();
281                 assert( p != null_ptr<typename iterator_base::value_ptr>() );
282                 return p->m_Data.first;
283             }
284
285             pair_ptr operator ->() const
286             {
287                 typename iterator_base::value_ptr p = iterator_base::operator ->();
288                 return p ? &(p->m_Data) : null_ptr<pair_ptr>();
289             }
290
291             pair_ref operator *() const
292             {
293                 typename iterator_base::value_ref p = iterator_base::operator *();
294                 return p.m_Data;
295             }
296
297             value_ref val() const
298             {
299                 typename iterator_base::value_ptr p = iterator_base::operator ->();
300                 assert( p != null_ptr<typename iterator_base::value_ptr>() );
301                 return p->m_Data.second;
302             }
303
304             /// Pre-increment
305             iterator_type& operator ++()
306             {
307                 iterator_base::operator ++();
308                 return *this;
309             }
310
311             template <bool C>
312             bool operator ==(iterator_type<C> const& i ) const
313             {
314                 return iterator_base::operator ==(i);
315             }
316             template <bool C>
317             bool operator !=(iterator_type<C> const& i ) const
318             {
319                 return iterator_base::operator !=(i);
320             }
321         };
322         //@endcond
323
324     public:
325         /// Forward iterator
326         /**
327             The forward iterator for Michael's list has some features:
328             - it has no post-increment operator
329             - to protect the value, the iterator contains a GC-specific guard + another guard is required locally for increment operator.
330               For some GC (gc::HP, gc::HRC), a guard is limited resource per thread, so an exception (or assertion) "no free guard"
331               may be thrown if a limit of guard count per thread is exceeded.
332             - The iterator cannot be moved across thread boundary since it contains GC's guard that is thread-private GC data.
333             - Iterator ensures thread-safety even if you delete the item that iterator points to. However, in case of concurrent
334               deleting operations it is no guarantee that you iterate all item in the list.
335
336             Therefore, the use of iterators in concurrent environment is not good idea. Use the iterator on the concurrent container
337             for debug purpose only.
338
339             The iterator interface to access item data:
340             - <tt> operator -> </tt> - returns a pointer to \ref value_type for iterator
341             - <tt> operator *</tt> - returns a reference (a const reference for \p const_iterator) to \ref value_type for iterator
342             - <tt> const key_type& key() </tt> - returns a key reference for iterator
343             - <tt> mapped_type& val() </tt> - retuns a value reference for iterator (const reference for \p const_iterator)
344
345             For both functions the iterator should not be equal to <tt> end() </tt>
346         */
347         typedef iterator_type<false>    iterator;
348
349         /// Const forward iterator
350         /**
351             For iterator's features and requirements see \ref iterator
352         */
353         typedef iterator_type<true>     const_iterator;
354
355         /// Returns a forward iterator addressing the first element in a list
356         /**
357             For empty list \code begin() == end() \endcode
358         */
359         iterator begin()
360         {
361             return iterator( head() );
362         }
363
364         /// Returns an iterator that addresses the location succeeding the last element in a list
365         /**
366             Do not use the value returned by <tt>end</tt> function to access any item.
367             Internally, <tt>end</tt> returning value equals to <tt>NULL</tt>.
368
369             The returned value can be used only to control reaching the end of the list.
370             For empty list \code begin() == end() \endcode
371         */
372         iterator end()
373         {
374             return iterator();
375         }
376
377         /// Returns a forward const iterator addressing the first element in a list
378         //@{
379         const_iterator begin() const
380         {
381             return const_iterator( head() );
382         }
383         const_iterator cbegin()
384         {
385             return const_iterator( head() );
386         }
387         //@}
388
389         /// Returns an const iterator that addresses the location succeeding the last element in a list
390         //@{
391         const_iterator end() const
392         {
393             return const_iterator();
394         }
395         const_iterator cend()
396         {
397             return const_iterator();
398         }
399         //@}
400
401     public:
402         /// Default constructor
403         /**
404             Initializes empty list
405         */
406         MichaelKVList()
407         {}
408
409         /// List desctructor
410         /**
411             Clears the list
412         */
413         ~MichaelKVList()
414         {
415             clear();
416         }
417
418         /// Inserts new node with key and default value
419         /**
420             The function creates a node with \p key and default value, and then inserts the node created into the list.
421
422             Preconditions:
423             - The \ref key_type should be constructible from value of type \p K.
424                 In trivial case, \p K is equal to \ref key_type.
425             - The \ref mapped_type should be default-constructible.
426
427             Returns \p true if inserting successful, \p false otherwise.
428         */
429         template <typename K>
430         bool insert( const K& key )
431         {
432             return insert_at( head(), key );
433         }
434
435         /// Inserts new node with a key and a value
436         /**
437             The function creates a node with \p key and value \p val, and then inserts the node created into the list.
438
439             Preconditions:
440             - The \ref key_type should be constructible from \p key of type \p K.
441             - The \ref mapped_type should be constructible from \p val of type \p V.
442
443             Returns \p true if inserting successful, \p false otherwise.
444         */
445         template <typename K, typename V>
446         bool insert( const K& key, const V& val )
447         {
448             // We cannot use insert with functor here
449             // because we cannot lock inserted node for updating
450             // Therefore, we use separate function
451             return insert_at( head(), key, val );
452         }
453
454         /// Inserts new node and initialize it by a functor
455         /**
456             This function inserts new node with key \p key and if inserting is successful then it calls
457             \p func functor with signature
458             \code
459                 struct functor {
460                     void operator()( value_type& item );
461                 };
462             \endcode
463
464             The argument \p item of user-defined functor \p func is the reference
465             to the list's item inserted. <tt>item.second</tt> is a reference to item's value that may be changed.
466             User-defined functor \p func should guarantee that during changing item's value no any other changes
467             could be made on this list's item by concurrent threads.
468             The user-defined functor can be passed by reference using <tt>boost::ref</tt>
469             and it is called only if inserting is successful.
470
471             The key_type should be constructible from value of type \p K.
472
473             The function allows to split creating of new item into two part:
474             - create item from \p key;
475             - insert new item into the list;
476             - if inserting is successful, initialize the value of item by calling \p func functor
477
478             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
479             it is preferable that the initialization should be completed only if inserting is successful.
480         */
481         template <typename K, typename Func>
482         bool insert_key( const K& key, Func func )
483         {
484             return insert_key_at( head(), key, func );
485         }
486
487         /// Ensures that the \p key exists in the list
488         /**
489             The operation performs inserting or changing data with lock-free manner.
490
491             If the \p key not found in the list, then the new item created from \p key
492             is inserted into the list (note that in this case the \ref key_type should be
493             copy-constructible from type \p K).
494             Otherwise, the functor \p func is called with item found.
495             The functor \p Func may be a function with signature:
496             \code
497                 void func( bool bNew, value_type& item );
498             \endcode
499             or a functor:
500             \code
501                 struct my_functor {
502                     void operator()( bool bNew, value_type& item );
503                 };
504             \endcode
505
506             with arguments:
507             - \p bNew - \p true if the item has been inserted, \p false otherwise
508             - \p item - item of the list
509
510             The functor may change any fields of the \p item.second that is \ref mapped_type;
511             however, \p func must guarantee that during changing no any other modifications
512             could be made on this item by concurrent threads.
513
514             You may pass \p func argument by reference using <tt>boost::ref</tt>.
515
516             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
517             \p second is true if new item has been added or \p false if the item with \p key
518             already is in the list.
519         */
520         template <typename K, typename Func>
521         std::pair<bool, bool> ensure( const K& key, Func f )
522         {
523             return ensure_at( head(), key, f );
524         }
525
526 #   ifdef CDS_EMPLACE_SUPPORT
527         /// Inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
528         /**
529             Returns \p true if inserting successful, \p false otherwise.
530
531             @note This function is available only for compiler that supports
532             variadic template and move semantics
533         */
534         template <typename K, typename... Args>
535         bool emplace( K&& key, Args&&... args )
536         {
537             return emplace_at( head(), std::forward<K>(key), std::forward<Args>(args)... );
538         }
539 #   endif
540
541         /// Deletes \p key from the list
542         /** \anchor cds_nonintrusive_MichaelKVList_hp_erase_val
543
544             Returns \p true if \p key is found and has been deleted, \p false otherwise
545         */
546         template <typename K>
547         bool erase( K const& key )
548         {
549             return erase_at( head(), key, intrusive_key_comparator() );
550         }
551
552         /// Deletes the item from the list using \p pred predicate for searching
553         /**
554             The function is an analog of \ref cds_nonintrusive_MichaelKVList_hp_erase_val "erase(K const&)"
555             but \p pred is used for key comparing.
556             \p Less functor has the interface like \p std::less.
557             \p pred must imply the same element order as the comparator used for building the list.
558         */
559         template <typename K, typename Less>
560         bool erase_with( K const& key, Less pred )
561         {
562             return erase_at( head(), key, typename options::template less_wrapper<Less>::type() );
563         }
564
565         /// Deletes \p key from the list
566         /** \anchor cds_nonintrusive_MichaelKVList_hp_erase_func
567             The function searches an item with key \p key, calls \p f functor
568             and deletes the item. If \p key is not found, the functor is not called.
569
570             The functor \p Func interface:
571             \code
572             struct extractor {
573                 void operator()(value_type& val) { ... }
574             };
575             \endcode
576             The functor may be passed by reference with <tt>boost:ref</tt>
577
578             Return \p true if key is found and deleted, \p false otherwise
579
580             See also: \ref erase
581         */
582         template <typename K, typename Func>
583         bool erase( K const& key, Func f )
584         {
585             return erase_at( head(), key, intrusive_key_comparator(), f );
586         }
587
588         /// Deletes the item from the list using \p pred predicate for searching
589         /**
590             The function is an analog of \ref cds_nonintrusive_MichaelKVList_hp_erase_func "erase(K const&, Func)"
591             but \p pred is used for key comparing.
592             \p Less functor has the interface like \p std::less.
593             \p pred must imply the same element order as the comparator used for building the list.
594         */
595         template <typename K, typename Less, typename Func>
596         bool erase_with( K const& key, Less pred, Func f )
597         {
598             return erase_at( head(), key, typename options::template less_wrapper<Less>::type(), f );
599         }
600
601         /// Extracts the item from the list with specified \p key
602         /** \anchor cds_nonintrusive_MichaelKVList_hp_extract
603             The function searches an item with key equal to \p key,
604             unlinks it from the list, and returns it in \p dest parameter.
605             If the item with key equal to \p key is not found the function returns \p false.
606
607             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
608
609             The \ref disposer specified in \p Traits class template parameter is called automatically
610             by garbage collector \p GC specified in class' template parameters when returned \ref guarded_ptr object
611             will be destroyed or released.
612             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
613
614             Usage:
615             \code
616             typedef cds::container::MichaelKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
617             ord_list theList;
618             // ...
619             {
620                 ord_list::guarded_ptr gp;
621                 theList.extract( gp, 5 );
622                 // Deal with gp
623                 // ...
624
625                 // Destructor of gp releases internal HP guard
626             }
627             \endcode
628         */
629         template <typename K>
630         bool extract( guarded_ptr& dest, K const& key )
631         {
632             return extract_at( head(), dest.guard(), key, intrusive_key_comparator() );
633         }
634
635         /// Extracts the item from the list with comparing functor \p pred
636         /**
637             The function is an analog of \ref cds_nonintrusive_MichaelKVList_hp_extract "extract(guarded_ptr&, K const&)"
638             but \p pred predicate is used for key comparing.
639
640             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
641             in any order.
642             \p pred must imply the same element order as the comparator used for building the list.
643         */
644         template <typename K, typename Less>
645         bool extract_with( guarded_ptr& dest, K const& key, Less pred )
646         {
647             return extract_at( head(), dest.guard(), key, typename options::template less_wrapper<Less>::type() );
648         }
649
650         /// Finds the key \p key
651         /** \anchor cds_nonintrusive_MichaelKVList_hp_find_val
652             The function searches the item with key equal to \p key
653             and returns \p true if it is found, and \p false otherwise
654         */
655         template <typename Q>
656         bool find( Q const& key )
657         {
658             return find_at( head(), key, intrusive_key_comparator() );
659         }
660
661         /// Finds the key \p val using \p pred predicate for searching
662         /**
663             The function is an analog of \ref cds_nonintrusive_MichaelKVList_hp_find_val "find(Q const&)"
664             but \p pred is used for key comparing.
665             \p Less functor has the interface like \p std::less.
666             \p pred must imply the same element order as the comparator used for building the list.
667         */
668         template <typename Q, typename Less>
669         bool find_with( Q const& key, Less pred )
670         {
671             return find_at( head(), key, typename options::template less_wrapper<Less>::type() );
672         }
673
674         /// Finds the key \p key and performs an action with it
675         /** \anchor cds_nonintrusive_MichaelKVList_hp_find_func
676             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
677             The interface of \p Func functor is:
678             \code
679             struct functor {
680                 void operator()( value_type& item );
681             };
682             \endcode
683             where \p item is the item found.
684
685             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
686
687             The functor may change <tt>item.second</tt> that is reference to value of node.
688             Note that the function is only guarantee that \p item cannot be deleted during functor is executing.
689             The function does not serialize simultaneous access to the list \p item. If such access is
690             possible you must provide your own synchronization schema to exclude unsafe item modifications.
691
692             The function returns \p true if \p key is found, \p false otherwise.
693         */
694         template <typename Q, typename Func>
695         bool find( Q const& key, Func f )
696         {
697             return find_at( head(), key, intrusive_key_comparator(), f );
698         }
699
700         /// Finds the key \p val using \p pred predicate for searching
701         /**
702             The function is an analog of \ref cds_nonintrusive_MichaelKVList_hp_find_func "find(Q&, Func)"
703             but \p pred is used for key comparing.
704             \p Less functor has the interface like \p std::less.
705             \p pred must imply the same element order as the comparator used for building the list.
706         */
707         template <typename Q, typename Less, typename Func>
708         bool find_with( Q const& key, Less pred, Func f )
709         {
710             return find_at( head(), key, typename options::template less_wrapper<Less>::type(), f );
711         }
712
713         /// Finds the \p key and return the item found
714         /** \anchor cds_nonintrusive_MichaelKVList_hp_get
715             The function searches the item with key equal to \p key
716             and assigns the item found to guarded pointer \p ptr.
717             The function returns \p true if \p key is found, and \p false otherwise.
718             If \p key is not found the \p ptr parameter is not changed.
719
720             The \ref disposer specified in \p Traits class template parameter is called
721             by garbage collector \p GC automatically when returned \ref guarded_ptr object
722             will be destroyed or released.
723             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
724
725             Usage:
726             \code
727             typedef cds::container::MichaelKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
728             ord_list theList;
729             // ...
730             {
731                 ord_list::guarded_ptr gp;
732                 if ( theList.get( gp, 5 )) {
733                     // Deal with gp
734                     //...
735                 }
736                 // Destructor of guarded_ptr releases internal HP guard
737             }
738             \endcode
739
740             Note the compare functor specified for class \p Traits template parameter
741             should accept a parameter of type \p K that can be not the same as \p key_type.
742         */
743         template <typename K>
744         bool get( guarded_ptr& ptr, K const& key )
745         {
746             return get_at( head(), ptr.guard(), key, intrusive_key_comparator() );
747         }
748
749         /// Finds the \p key and return the item found
750         /**
751             The function is an analog of \ref cds_nonintrusive_MichaelKVList_hp_get "get( guarded_ptr& ptr, K const&)"
752             but \p pred is used for comparing the keys.
753
754             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
755             in any order.
756             \p pred must imply the same element order as the comparator used for building the list.
757         */
758         template <typename K, typename Less>
759         bool get_with( guarded_ptr& ptr, K const& key, Less pred )
760         {
761             return get_at( head(), ptr.guard(), key, typename options::template less_wrapper<Less>::type() );
762         }
763
764         /// Checks if the list is empty
765         bool empty() const
766         {
767             return base_class::empty();
768         }
769
770         /// Returns list's item count
771         /**
772             The value returned depends on opt::item_counter option. For atomicity::empty_item_counter,
773             this function always returns 0.
774
775             <b>Warning</b>: even if you use real item counter and it returns 0, this fact is not mean that the list
776             is empty. To check list emptyness use \ref empty() method.
777         */
778         size_t size() const
779         {
780             return base_class::size();
781         }
782
783         /// Clears the list
784         /**
785             Post-condition: the list is empty
786         */
787         void clear()
788         {
789             base_class::clear();
790         }
791
792     protected:
793         //@cond
794         bool insert_node_at( head_type& refHead, node_type * pNode )
795         {
796             assert( pNode != null_ptr<node_type *>() );
797             scoped_node_ptr p( pNode );
798             if ( base_class::insert_at( refHead, *pNode )) {
799                 p.release();
800                 return true;
801             }
802             return false;
803         }
804
805         template <typename K>
806         bool insert_at( head_type& refHead, const K& key )
807         {
808             return insert_node_at( refHead, alloc_node( key ));
809         }
810
811         template <typename K, typename V>
812         bool insert_at( head_type& refHead, const K& key, const V& val )
813         {
814             return insert_node_at( refHead, alloc_node( key, val ));
815         }
816
817         template <typename K, typename Func>
818         bool insert_key_at( head_type& refHead, const K& key, Func f )
819         {
820             scoped_node_ptr pNode( alloc_node( key ));
821
822 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
823             if ( base_class::insert_at( refHead, *pNode, [&f](node_type& node){ cds::unref(f)( node.m_Data ); }))
824 #       else
825             insert_functor<Func>  wrapper( f );
826             if ( base_class::insert_at( refHead, *pNode, cds::ref(wrapper) ))
827 #       endif
828             {
829                 pNode.release();
830                 return true;
831             }
832             return false;
833         }
834
835 #   ifdef CDS_EMPLACE_SUPPORT
836         template <typename K, typename... Args>
837         bool emplace_at( head_type& refHead, K&& key, Args&&... args )
838         {
839             return insert_node_at( refHead, alloc_node( std::forward<K>(key), std::forward<Args>(args)... ));
840         }
841 #   endif
842
843         template <typename K, typename Func>
844         std::pair<bool, bool> ensure_at( head_type& refHead, const K& key, Func f )
845         {
846             scoped_node_ptr pNode( alloc_node( key ));
847
848 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
849             std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode,
850                 [&f]( bool bNew, node_type& node, node_type& ){ cds::unref(f)( bNew, node.m_Data ); });
851 #       else
852             ensure_functor<Func> wrapper( f );
853             std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode, cds::ref(wrapper));
854 #       endif
855             if ( ret.first && ret.second )
856                 pNode.release();
857
858             return ret;
859         }
860
861         template <typename K, typename Compare>
862         bool erase_at( head_type& refHead, K const& key, Compare cmp )
863         {
864             return base_class::erase_at( refHead, key, cmp );
865         }
866
867         template <typename K, typename Compare, typename Func>
868         bool erase_at( head_type& refHead, K const& key, Compare cmp, Func f )
869         {
870 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
871             return base_class::erase_at( refHead, key, cmp, [&f]( node_type const & node ){ cds::unref(f)( const_cast<value_type&>(node.m_Data)); });
872 #       else
873             erase_functor<Func> wrapper( f );
874             return base_class::erase_at( refHead, key, cmp, cds::ref(wrapper) );
875 #       endif
876         }
877         template <typename K, typename Compare>
878         bool extract_at( head_type& refHead, typename gc::Guard& dest, K const& key, Compare cmp )
879         {
880             return base_class::extract_at( refHead, dest, key, cmp );
881         }
882
883         template <typename K, typename Compare>
884         bool find_at( head_type& refHead, K const& key, Compare cmp )
885         {
886             return base_class::find_at( refHead, key, cmp );
887         }
888
889         template <typename K, typename Compare, typename Func>
890         bool find_at( head_type& refHead, K& key, Compare cmp, Func f )
891         {
892 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
893             return base_class::find_at( refHead, key, cmp, [&f](node_type& node, K const&){ cds::unref(f)( node.m_Data ); });
894 #       else
895             find_functor<Func>  wrapper( f );
896             return base_class::find_at( refHead, key, cmp, cds::ref(wrapper) );
897 #       endif
898         }
899
900         template <typename K, typename Compare>
901         bool get_at( head_type& refHead, typename gc::Guard& guard, K const& key, Compare cmp )
902         {
903             return base_class::get_at( refHead, guard, key, cmp );
904         }
905
906         //@endcond
907     };
908
909 }}  // namespace cds::container
910
911 #endif  // #ifndef __CDS_CONTAINER_MICHAEL_KVLIST_IMPL_H