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