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