Removed trailing spaces
[libcds.git] / cds / container / michael_kvlist_rcu.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_MICHAEL_KVLIST_RCU_H
32 #define CDSLIB_CONTAINER_MICHAEL_KVLIST_RCU_H
33
34 #include <memory>
35 #include <functional>   // ref
36 #include <cds/container/details/michael_list_base.h>
37 #include <cds/intrusive/michael_list_rcu.h>
38 #include <cds/container/details/make_michael_kvlist.h>
39
40 namespace cds { namespace container {
41
42     /// Michael's ordered list (key-value pair), template specialization for \ref cds_urcu_desc "RCU"
43     /** @ingroup cds_nonintrusive_list
44         \anchor cds_nonintrusive_MichaelKVList_rcu
45
46         This is key-value variation of non-intrusive \ref cds_nonintrusive_MichaelList_rcu "MichaelList".
47         Like standard container, this implementation split a value stored into two part -
48         constant key and alterable value.
49
50         Usually, ordered single-linked list is used as a building block for the hash table implementation.
51         The complexity of searching is <tt>O(N)</tt>.
52
53         Template arguments:
54         - \p RCU - one of \ref cds_urcu_gc "RCU type"
55         - \p Key - key type of an item stored in the list. It should be copy-constructible
56         - \p Value - value type stored in a list
57         - \p Traits - type traits, default is \p michael_list::traits
58
59         @note Before including <tt><cds/container/michael_kvlist_rcu.h></tt> you should include appropriate RCU header file,
60         see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files.
61
62         It is possible to declare option-based list using \p cds::container::michael_list::make_traits metafunction istead of \p Traits template
63         argument. For example, the following traits-based declaration of Michael's list
64         \code
65         #include <cds/urcu/general_buffered.h>
66         #include <cds/container/michael_kvlist_rcu.h>
67         // Declare comparator for the item
68         struct my_compare {
69             int operator ()( int i1, int i2 )
70             {
71                 return i1 - i2;
72             }
73         };
74
75         // Declare traits
76         struct my_traits: public cds::container::michael_list::traits
77         {
78             typedef my_compare compare;
79         };
80
81         // Declare traits-based list
82         typedef cds::container::MichaelKVList< cds::urcu::gc< cds::urcu::general_buffered<> >, int, int, my_traits > traits_based_list;
83         \endcode
84
85         is equivalent for the following option-based list
86         \code
87         #include <cds/urcu/general_buffered.h>
88         #include <cds/container/michael_kvlist_rcu.h>
89
90         // my_compare is the same
91
92         // Declare option-based list
93         typedef cds::container::MichaelKVList< cds::urcu::gc< cds::urcu::general_buffered<> >, int, int,
94             typename cds::container::michael_list::make_traits<
95                 cds::container::opt::compare< my_compare >     // item comparator option
96             >::type
97         >     option_based_list;
98         \endcode
99     */
100     template <
101         typename RCU,
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< cds::urcu::gc<RCU>, Key, Value, Traits >:
111 #ifdef CDS_DOXYGEN_INVOKED
112         protected intrusive::MichaelList< cds::urcu::gc<RCU>, implementation_defined, Traits >
113 #else
114         protected details::make_michael_kvlist< cds::urcu::gc<RCU>, Key, Value, Traits >::type
115 #endif
116     {
117         //@cond
118         typedef details::make_michael_kvlist< cds::urcu::gc<RCU>, Key, Value, Traits > maker;
119         typedef typename maker::type  base_class;
120         //@endcond
121
122     public:
123         typedef cds::urcu::gc<RCU>  gc;   ///< Garbage collector
124
125 #ifdef CDS_DOXYGEN_INVOKED
126         typedef Key                                 key_type;      ///< Key type
127         typedef Value                               mapped_type;   ///< Type of value stored in the list
128         typedef std::pair<key_type const, mapped_type> value_type; ///< key/value pair stored in the list
129 #else
130         typedef typename maker::key_type   key_type;
131         typedef typename maker::value_type mapped_type;
132         typedef typename maker::pair_type  value_type;
133 #endif
134         typedef Traits traits; ///< List traits
135
136         typedef typename base_class::back_off     back_off;       ///< Back-off strategy
137         typedef typename maker::allocator_type    allocator_type; ///< Allocator type used for allocate/deallocate the nodes
138         typedef typename base_class::item_counter item_counter;   ///< Item counting policy
139         typedef typename maker::key_comparator    key_comparator; ///< key comparison functor
140         typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See \p michael_list::traits::memory_model
141         typedef typename base_class::stat         stat;           ///< Internal statistics
142         typedef typename base_class::rcu_check_deadlock rcu_check_deadlock ; ///< RCU deadlock checking policy
143
144         typedef typename gc::scoped_lock    rcu_lock ;  ///< RCU scoped lock
145         static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal; ///< Group of \p extract_xxx functions do not require external locking
146
147         //@cond
148         // Rebind traits (split-list support)
149         template <typename... Options>
150         struct rebind_traits {
151             typedef MichaelKVList<
152                 gc
153                 , key_type, mapped_type
154                 , typename cds::opt::make_options< traits, Options...>::type
155             > type;
156         };
157
158         // Stat selector
159         template <typename Stat>
160         using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >;
161         //@endcond
162
163     protected:
164         //@cond
165         typedef typename base_class::value_type     node_type;
166         typedef typename maker::cxx_allocator     cxx_allocator;
167         typedef typename maker::node_deallocator  node_deallocator;
168         typedef typename maker::intrusive_traits::compare  intrusive_key_comparator;
169
170         typedef typename base_class::atomic_node_ptr head_type;
171
172         struct node_disposer {
173             void operator()( node_type * pNode )
174             {
175                 free_node( pNode );
176             }
177         };
178         typedef std::unique_ptr< node_type, node_disposer >     scoped_node_ptr;
179         //@endcond
180
181     public:
182         /// pointer to extracted node
183         using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer,
184             cds::urcu::details::conventional_exempt_pair_cast<node_type, value_type>
185         >;
186
187     private:
188         //@cond
189         struct raw_ptr_converter
190         {
191             value_type * operator()( node_type * p ) const
192             {
193                return p ? &p->m_Data : nullptr;
194             }
195
196             value_type& operator()( node_type& n ) const
197             {
198                 return n.m_Data;
199             }
200
201             value_type const& operator()( node_type const& n ) const
202             {
203                 return n.m_Data;
204             }
205         };
206         //@endcond
207
208     public:
209         /// Result of \p get(), \p get_with() functions - pointer to the node found
210         typedef cds::urcu::raw_ptr_adaptor< value_type, typename base_class::raw_ptr, raw_ptr_converter > raw_ptr;
211
212
213     protected:
214         //@cond
215         template <bool IsConst>
216         class iterator_type: protected base_class::template iterator_type<IsConst>
217         {
218             typedef typename base_class::template iterator_type<IsConst>    iterator_base;
219
220             iterator_type( head_type const& pNode )
221                 : iterator_base( pNode )
222             {}
223
224             friend class MichaelKVList;
225
226         public:
227             typedef typename cds::details::make_const_type<mapped_type, IsConst>::reference  value_ref;
228             typedef typename cds::details::make_const_type<mapped_type, IsConst>::pointer    value_ptr;
229
230             typedef typename cds::details::make_const_type<value_type,  IsConst>::reference  pair_ref;
231             typedef typename cds::details::make_const_type<value_type,  IsConst>::pointer    pair_ptr;
232
233             iterator_type()
234             {}
235
236             iterator_type( iterator_type const& src )
237                 : iterator_base( src )
238             {}
239
240             key_type const& key() const
241             {
242                 typename iterator_base::value_ptr p = iterator_base::operator ->();
243                 assert( p != nullptr );
244                 return p->m_Data.first;
245             }
246
247             pair_ptr operator ->() const
248             {
249                 typename iterator_base::value_ptr p = iterator_base::operator ->();
250                 return p ? &(p->m_Data) : nullptr;
251             }
252
253             pair_ref operator *() const
254             {
255                 typename iterator_base::value_ref p = iterator_base::operator *();
256                 return p.m_Data;
257             }
258
259             value_ref val() const
260             {
261                 typename iterator_base::value_ptr p = iterator_base::operator ->();
262                 assert( p != nullptr );
263                 return p->m_Data.second;
264             }
265
266             /// Pre-increment
267             iterator_type& operator ++()
268             {
269                 iterator_base::operator ++();
270                 return *this;
271             }
272
273             template <bool C>
274             bool operator ==(iterator_type<C> const& i ) const
275             {
276                 return iterator_base::operator ==(i);
277             }
278             template <bool C>
279             bool operator !=(iterator_type<C> const& i ) const
280             {
281                 return iterator_base::operator !=(i);
282             }
283         };
284         //@endcond
285
286     public:
287     ///@name Forward iterators
288     //@{
289         /// Forward iterator
290         /**
291             You may safely use iterators in multi-threaded environment only under external RCU lock.
292             Otherwise, a program crash is possible if another thread deletes the item the iterator points to.
293         */
294         typedef iterator_type<false>    iterator;
295
296         /// Const forward iterator
297         typedef iterator_type<true>     const_iterator;
298
299         /// Returns a forward iterator addressing the first element in a list
300         /**
301             For empty list \code begin() == end() \endcode
302         */
303         iterator begin()
304         {
305             return iterator( head() );
306         }
307
308         /// Returns an iterator that addresses the location succeeding the last element in a list
309         /**
310             Do not use the value returned by <tt>end</tt> function to access any item.
311             Internally, <tt>end</tt> returning value equals to \p nullptr.
312
313             The returned value can be used only to control reaching the end of the list.
314             For empty list \code begin() == end() \endcode
315         */
316         iterator end()
317         {
318             return iterator();
319         }
320
321         /// Returns a forward const iterator addressing the first element in a list
322         const_iterator begin() const
323         {
324             return const_iterator( head() );
325         }
326         /// Returns a forward const iterator addressing the first element in a list
327         const_iterator cbegin() const
328         {
329             return const_iterator( head() );
330         }
331
332         /// Returns an const iterator that addresses the location succeeding the last element in a list
333         const_iterator end() const
334         {
335             return const_iterator();
336         }
337         /// Returns an const iterator that addresses the location succeeding the last element in a list
338         const_iterator cend() const
339         {
340             return const_iterator();
341         }
342     //@}
343
344     public:
345         /// Default constructor
346         /**
347             Initializes empty list
348         */
349         MichaelKVList()
350         {}
351
352         //@cond
353         template <typename Stat, typename = std::enable_if<std::is_same<stat, michael_list::wrapped_stat<Stat>>::value >>
354         explicit MichaelKVList( Stat& st )
355             : base_class( st )
356         {}
357         //@endcond
358
359         /// List destructor
360         /**
361             Clears the list
362         */
363         ~MichaelKVList()
364         {
365             clear();
366         }
367
368         /// Inserts new node with key and default value
369         /**
370             The function creates a node with \p key and default value, and then inserts the node created into the list.
371
372             Preconditions:
373             - The \ref key_type should be constructible from value of type \p K.
374                 In trivial case, \p K is equal to \ref key_type.
375             - The \ref mapped_type should be default-constructible.
376
377             The function applies RCU lock internally.
378
379             Returns \p true if inserting successful, \p false otherwise.
380         */
381         template <typename K>
382         bool insert( const K& key )
383         {
384             return insert_at( head(), key );
385         }
386
387         /// Inserts new node with a key and a value
388         /**
389             The function creates a node with \p key and value \p val, and then inserts the node created into the list.
390
391             Preconditions:
392             - The \ref key_type should be constructible from \p key of type \p K.
393             - The \ref mapped_type should be constructible from \p val of type \p V.
394
395             The function applies RCU lock internally.
396
397             Returns \p true if inserting successful, \p false otherwise.
398         */
399         template <typename K, typename V>
400         bool insert( const K& key, const V& val )
401         {
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 list's 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
420             The key_type should be constructible from value of type \p K.
421
422             The function allows to split creating of new item into two part:
423             - create item from \p key;
424             - insert new item into the list;
425             - if inserting is successful, initialize the value of item by calling \p func functor
426
427             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
428             it is preferable that the initialization should be completed only if inserting is successful.
429
430             The function applies RCU lock internally.
431
432             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
433         */
434         template <typename K, typename Func>
435         bool insert_with( const K& key, Func func )
436         {
437             return insert_with_at( head(), key, func );
438         }
439
440         /// Updates an element with given \p key
441         /**
442             The operation performs inserting or changing data with lock-free manner.
443
444             If the \p key not found in the list, then the new item created from \p key
445             is inserted into the list (note that in this case the \ref key_type should be
446             copy-constructible from type \p K).
447             Otherwise, the functor \p func is called with item found.
448             The functor \p Func may be a function with signature:
449             \code
450                 void func( bool bNew, value_type& item );
451             \endcode
452             or a functor:
453             \code
454                 struct my_functor {
455                     void operator()( bool bNew, value_type& item );
456                 };
457             \endcode
458
459             with arguments:
460             - \p bNew - \p true if the item has been inserted, \p false otherwise
461             - \p item - item of the list
462
463             The functor may change any fields of the \p item.second that is \ref mapped_type;
464             however, \p func must guarantee that during changing no any other modifications
465             could be made on this item by concurrent threads.
466
467             The function applies RCU lock internally.
468
469             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
470             \p second is true if new item has been added or \p false if the item with \p key
471             already is in the list.
472
473             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
474         */
475         /// Updates data by \p key
476         /**
477             The operation performs inserting or replacing the element with lock-free manner.
478
479             If the \p key not found in the list, then the new item created from \p key
480             will be inserted iff \p bAllowInsert is \p true.
481             (note that in this case the \ref key_type should be constructible from type \p K).
482             Otherwise, if \p key is found, the functor \p func is called with item found.
483
484             The functor \p Func signature is:
485             \code
486                 struct my_functor {
487                     void operator()( bool bNew, value_type& item );
488                 };
489             \endcode
490             with arguments:
491             - \p bNew - \p true if the item has been inserted, \p false otherwise
492             - \p item - the item found or inserted
493
494             The functor may change any fields of the \p item.second that is \ref mapped_type;
495             however, \p func must guarantee that during changing no any other modifications
496             could be made on this item by concurrent threads.
497
498             The function applies RCU lock internally.
499
500             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
501             \p second is true if new item has been added or \p false if the item with \p key
502             already exists.
503
504             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
505         */
506         template <typename K, typename Func>
507         std::pair<bool, bool> update( const K& key, Func func, bool bAllowInsert = true )
508         {
509             return update_at( head(), key, func, bAllowInsert );
510         }
511         //@cond
512         template <typename K, typename Func>
513         CDS_DEPRECATED("ensure() is deprecated, use update()")
514         std::pair<bool, bool> ensure( const K& key, Func f )
515         {
516             return update( key, f, true );
517         }
518         //@endcond
519
520         /// Inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
521         /**
522             Returns \p true if inserting successful, \p false otherwise.
523
524             The function applies RCU lock internally.
525         */
526         template <typename K, typename... Args>
527         bool emplace( K&& key, Args&&... args )
528         {
529             return emplace_at( head(), std::forward<K>(key), std::forward<Args>(args)... );
530         }
531
532         /// Deletes \p key from the list
533         /** \anchor cds_nonintrusive_MichaelKVList_rcu_erase
534
535             RCU \p synchronize method can be called. RCU should not be locked.
536
537             Returns \p true if \p key is found and has been deleted, \p false otherwise
538         */
539         template <typename K>
540         bool erase( K const& key )
541         {
542             return erase_at( head(), key, intrusive_key_comparator() );
543         }
544
545         /// Deletes the item from the list using \p pred predicate for searching
546         /**
547             The function is an analog of \ref cds_nonintrusive_MichaelKVList_rcu_erase "erase(K const&)"
548             but \p pred is used for key comparing.
549             \p Less functor has the interface like \p std::less.
550             \p pred must imply the same element order as the comparator used for building the list.
551         */
552         template <typename K, typename Less>
553         bool erase_with( K const& key, Less pred )
554         {
555             CDS_UNUSED( pred );
556             return erase_at( head(), key, typename maker::template less_wrapper<Less>::type() );
557         }
558
559         /// Deletes \p key from the list
560         /** \anchor cds_nonintrusive_MichaelKVList_rcu_erase_func
561             The function searches an item with key \p key, calls \p f functor
562             and deletes the item. If \p key is not found, the functor is not called.
563
564             The functor \p Func interface:
565             \code
566             struct functor {
567                 void operator()(value_type& val) { ... }
568             };
569             \endcode
570
571             RCU \p synchronize method can be called. RCU should not be locked.
572
573             Return \p true if key is found and deleted, \p false otherwise
574
575             See also: \ref erase
576         */
577         template <typename K, typename Func>
578         bool erase( K const& key, Func f )
579         {
580             return erase_at( head(), key, intrusive_key_comparator(), f );
581         }
582
583         /// Deletes the item from the list using \p pred predicate for searching
584         /**
585             The function is an analog of \ref cds_nonintrusive_MichaelKVList_rcu_erase_func "erase(K const&, Func)"
586             but \p pred is used for key comparing.
587             \p Less functor has the interface like \p std::less.
588             \p pred must imply the same element order as the comparator used for building the list.
589         */
590         template <typename K, typename Less, typename Func>
591         bool erase_with( K const& key, Less pred, Func f )
592         {
593             CDS_UNUSED( pred );
594             return erase_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
595         }
596
597         /// Extracts an item from the list
598         /**
599         @anchor cds_nonintrusive_MichaelKVList_rcu_extract
600             The function searches an item with key equal to \p key in the list,
601             unlinks it from the list, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
602             If \p key is not found the function returns an empty \p exempt_ptr.
603
604             @note The function does NOT dispose the item found.
605             It just excludes the item from the list and returns a pointer to item found.
606             You shouldn't lock RCU before calling this function.
607
608             \code
609             #include <cds/urcu/general_buffered.h>
610             #include <cds/container/michael_kvlist_rcu.h>
611
612             typedef cds::urcu::gc< general_buffered<> > rcu;
613             typedef cds::container::MichaelKVList< rcu, int, Foo > rcu_michael_list;
614
615             rcu_michael_list theList;
616             // ...
617
618             rcu_michael_list::exempt_ptr p;
619
620             // The RCU should NOT be locked when extract() is called!
621             assert( !rcu::is_locked() );
622
623             // extract() call
624             p = theList.extract( 10 );
625             if ( p ) {
626                 // do something with p
627                 ...
628             }
629
630             // we may safely release extracted pointer here.
631             // release() passes the pointer to RCU reclamation cycle.
632             p.release();
633             \endcode
634         */
635         template <typename K>
636         exempt_ptr extract( K const& key )
637         {
638             return exempt_ptr( extract_at( head(), key, intrusive_key_comparator() ));
639         }
640
641         /// Extracts an item from the list using \p pred predicate for searching
642         /**
643             This function is the analog for \p extract(K const&).
644             The \p pred is a predicate used for key comparing.
645             \p Less has the interface like \p std::less.
646             \p pred must imply the same element order as \ref key_comparator.
647         */
648         template <typename K, typename Less>
649         exempt_ptr extract_with( K const& key, Less pred )
650         {
651             CDS_UNUSED( pred );
652             return exempt_ptr( extract_at( head(), key, typename maker::template less_wrapper<Less>::type() ));
653         }
654
655         /// Checks whether the list contains \p key
656         /**
657             The function searches the item with key equal to \p key
658             and returns \p true if it is found, and \p false otherwise.
659
660             The function applies RCU lock internally.
661         */
662         template <typename Q>
663         bool contains( Q const& key )
664         {
665             return find_at( head(), key, intrusive_key_comparator() );
666         }
667         //@cond
668         template <typename Q>
669         CDS_DEPRECATED("deprecated, use contains()")
670         bool find( Q const& key )
671         {
672             return contains( key );
673         }
674         //@endcond
675
676         /// Checks whether the map contains \p key using \p pred predicate for searching
677         /**
678             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
679             \p Less functor has the interface like \p std::less.
680             \p Less must imply the same element order as the comparator used for building the list.
681
682             The function applies RCU lock internally.
683         */
684         template <typename Q, typename Less>
685         bool contains( Q const& key, Less pred )
686         {
687             CDS_UNUSED( pred );
688             return find_at( head(), key, typename maker::template less_wrapper<Less>::type() );
689         }
690         //@cond
691         template <typename Q, typename Less>
692         CDS_DEPRECATED("deprecated, use contains()")
693         bool find_with( Q const& key, Less pred )
694         {
695             return contains( key, pred );
696         }
697         //@endcond
698
699         /// Finds \p key and performs an action with it
700         /** \anchor cds_nonintrusive_MichaelKVList_rcu_find_func
701             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
702             The interface of \p Func functor is:
703             \code
704             struct functor {
705                 void operator()( value_type& item );
706             };
707             \endcode
708             where \p item is the item found.
709
710             The functor may change <tt>item.second</tt> that is reference to value of node.
711             Note that the function is only guarantee that \p item cannot be deleted during functor is executing.
712             The function does not serialize simultaneous access to the list \p item. If such access is
713             possible you must provide your own synchronization schema to exclude unsafe item modifications.
714
715             The function makes RCU lock internally.
716
717             The function returns \p true if \p key is found, \p false otherwise.
718         */
719         template <typename Q, typename Func>
720         bool find( Q const& key, Func f )
721         {
722             return find_at( head(), key, intrusive_key_comparator(), f );
723         }
724
725         /// Finds the key \p val using \p pred predicate for searching
726         /**
727             The function is an analog of \ref cds_nonintrusive_MichaelKVList_rcu_find_func "find(Q const&, Func)"
728             but \p pred is used for key comparing.
729             \p Less functor has the interface like \p std::less.
730             \p pred must imply the same element order as the comparator used for building the list.
731         */
732         template <typename Q, typename Less, typename Func>
733         bool find_with( Q const& key, Less pred, Func f )
734         {
735             CDS_UNUSED( pred );
736             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
737         }
738
739         /// Finds \p key and return the item found
740         /** \anchor cds_nonintrusive_MichaelKVList_rcu_get
741             The function searches the item with \p key and returns the pointer to item found.
742             If \p key is not found it returns an empty \p raw_ptr object.
743
744             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
745
746             RCU should be locked before call of this function.
747             Returned item is valid only while RCU is locked:
748             \code
749             typedef cds::container::MichaelKVList< cds::urcu::gc< cds::urcu::general_buffered<> >, int, foo, my_traits > ord_list;
750             ord_list theList;
751             // ...
752             tyename ord_list::raw_ptr rp;
753             {
754                 // Lock RCU
755                 ord_list::rcu_lock lock;
756
757                 rp = theList.get( 5 );
758                 if ( rp ) {
759                     // Deal with rp
760                     //...
761                 }
762                 // Unlock RCU by rcu_lock destructor
763             }
764             // rp can be released at any time after RCU has been unlocked
765             rp.release();
766             \endcode
767         */
768         template <typename K>
769         raw_ptr get( K const& key )
770         {
771             return get_at( head(), key, intrusive_key_comparator());
772         }
773
774         /// Finds \p key and return the item found
775         /**
776             The function is an analog of \ref cds_nonintrusive_MichaelKVList_rcu_get "get(K const&)"
777             but \p pred is used for comparing the keys.
778
779             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
780             in any order.
781             \p pred must imply the same element order as the comparator used for building the list.
782         */
783         template <typename K, typename Less>
784         raw_ptr get_with( K const& key, Less pred )
785         {
786             CDS_UNUSED( pred );
787             return get_at( head(), key, typename maker::template less_wrapper<Less>::type() );
788         }
789
790         /// Checks if the list is empty
791         bool empty() const
792         {
793             return base_class::empty();
794         }
795
796         /// Returns list's item count
797         /**
798             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
799             this function always returns 0.
800
801             @note Even if you use real item counter and it returns 0, this fact does not mean that the list
802             is empty. To check list emptyness use \p empty() method.
803         */
804         size_t size() const
805         {
806             return base_class::size();
807         }
808
809         /// Returns const reference to internal statistics
810         stat const& statistics() const
811         {
812             return base_class::statistics();
813         }
814
815         /// Clears the list
816         /**
817             Post-condition: the list is empty
818         */
819         void clear()
820         {
821             base_class::clear();
822         }
823
824     protected:
825         //@cond
826         bool insert_node_at( head_type& refHead, node_type * pNode )
827         {
828             assert( pNode != nullptr );
829             scoped_node_ptr p( pNode );
830             if ( base_class::insert_at( refHead, *pNode )) {
831                 p.release();
832                 return true;
833             }
834             return false;
835         }
836
837         template <typename K>
838         bool insert_at( head_type& refHead, const K& key )
839         {
840             return insert_node_at( refHead, alloc_node( key ));
841         }
842
843         template <typename K, typename V>
844         bool insert_at( head_type& refHead, const K& key, const V& val )
845         {
846             return insert_node_at( refHead, alloc_node( key, val ));
847         }
848
849         template <typename K, typename Func>
850         bool insert_with_at( head_type& refHead, const K& key, Func f )
851         {
852             scoped_node_ptr pNode( alloc_node( key ));
853
854             if ( base_class::insert_at( refHead, *pNode, [&f](node_type& node){ f( node.m_Data ); })) {
855                 pNode.release();
856                 return true;
857             }
858             return false;
859         }
860
861         template <typename K, typename... Args>
862         bool emplace_at( head_type& refHead, K&& key, Args&&... args )
863         {
864             return insert_node_at( refHead, alloc_node( std::forward<K>(key), std::forward<Args>(args)... ));
865         }
866
867         template <typename K, typename Func>
868         std::pair<bool, bool> update_at( head_type& refHead, const K& key, Func f, bool bAllowInsert )
869         {
870             scoped_node_ptr pNode( alloc_node( key ));
871
872             std::pair<bool, bool> ret = base_class::update_at( refHead, *pNode,
873                 [&f]( bool bNew, node_type& node, node_type& ){ f( bNew, node.m_Data ); },
874                 bAllowInsert );
875             if ( ret.first && ret.second )
876                 pNode.release();
877
878             return ret;
879         }
880
881         template <typename K, typename Compare>
882         bool erase_at( head_type& refHead, K const& key, Compare cmp )
883         {
884             return base_class::erase_at( refHead, key, cmp );
885         }
886
887         template <typename K, typename Compare, typename Func>
888         bool erase_at( head_type& refHead, K const& key, Compare cmp, Func f )
889         {
890             return base_class::erase_at( refHead, key, cmp, [&f]( node_type const & node ){ f( const_cast<value_type&>(node.m_Data)); });
891         }
892
893         template <typename K, typename Compare>
894         node_type * extract_at( head_type& refHead, K const& key, Compare cmp )
895         {
896             return base_class::extract_at( refHead, key, cmp );
897         }
898
899         template <typename K, typename Compare>
900         bool find_at( head_type& refHead, K const& key, Compare cmp )
901         {
902             return base_class::find_at( refHead, key, cmp, [](node_type&, K const&) {} );
903         }
904
905         template <typename K, typename Compare, typename Func>
906         bool find_at( head_type& refHead, K& key, Compare cmp, Func f )
907         {
908             return base_class::find_at( refHead, key, cmp, [&f](node_type& node, K const&){ f( node.m_Data ); });
909         }
910
911         template <typename K, typename Compare>
912         raw_ptr get_at( head_type& refHead, K const& val, Compare cmp )
913         {
914             return raw_ptr( base_class::get_at( refHead, val, cmp ));
915         }
916
917         template <typename K>
918         static node_type * alloc_node( const K& key )
919         {
920             return cxx_allocator().New( key );
921         }
922
923         template <typename K, typename V>
924         static node_type * alloc_node( const K& key, const V& val )
925         {
926             return cxx_allocator().New( key, val );
927         }
928
929         template <typename K, typename... Args>
930         static node_type * alloc_node( K&& key, Args&&... args )
931         {
932             return cxx_allocator().MoveNew( std::forward<K>( key ), std::forward<Args>( args )... );
933         }
934
935         static void free_node( node_type * pNode )
936         {
937             cxx_allocator().Delete( pNode );
938         }
939
940         head_type& head()
941         {
942             return base_class::m_pHead;
943         }
944
945         head_type& head() const
946         {
947             return const_cast<head_type&>(base_class::m_pHead);
948         }
949         //@endcond
950     };
951
952 }}  // namespace cds::container
953
954 #endif  // #ifndef CDSLIB_CONTAINER_MICHAEL_KVLIST_RCU_H