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