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