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