Uses different pass count for different parallel queue test cases
[libcds.git] / cds / container / impl / iterable_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-2017
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_ITERABLE_LIST_H
32 #define CDSLIB_CONTAINER_IMPL_ITERABLE_LIST_H
33
34 #include <cds/container/details/make_iterable_list.h>
35 #include <memory>
36
37 namespace cds { namespace container {
38
39     /// Iterable ordered list
40     /** @ingroup cds_nonintrusive_list
41         \anchor cds_nonintrusive_IterableList_gc
42
43         This lock-free list implementation supports thread-safe iterators.
44
45         Usually, ordered single-linked list is used as a building block for the hash table implementation.
46         Iterable list is suitable for almost append-only hash table because the list doesn't delete
47         its internal node when erasing a key but it is marked them as empty to be reused in the future.
48         However, plenty of empty nodes degrades performance.
49
50         The complexity of searching is <tt>O(N)</tt>.
51
52         Template arguments:
53         - \p GC - Garbage collector used.
54         - \p T - type to be stored in the list.
55         - \p Traits - type traits, default is \p iterable_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         \p IterableKVList is a key-value version of iterable 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::iterable_list::make_traits metafunction istead of \p Traits template
65         argument. For example, the following traits-based declaration of gc::HP iterable list
66         \code
67         #include <cds/container/iterable_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::iterable_list::traits
78         {
79             typedef my_compare compare;
80         };
81
82         // Declare traits-based list
83         typedef cds::container::IterableList< 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/iterable_list_hp.h>
89
90         // my_compare is the same
91
92         // Declare option-based list
93         typedef cds::container::IterableList< cds::gc::HP, int,
94             typename cds::container::iterable_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/iterable_list_hp.h> \endcode
104         - for gc::DHP: \code #include <cds/container/iterable_list_dhp.h> \endcode
105         - for \ref cds_urcu_desc "RCU": \code #include <cds/container/iterable_list_rcu.h> \endcode
106     */
107     template <
108         typename GC,
109         typename T,
110 #ifdef CDS_DOXYGEN_INVOKED
111         typename Traits = iterable_list::traits
112 #else
113         typename Traits
114 #endif
115     >
116     class IterableList:
117 #ifdef CDS_DOXYGEN_INVOKED
118         protected intrusive::IterableList< GC, T, Traits >
119 #else
120         protected details::make_iterable_list< GC, T, Traits >::type
121 #endif
122     {
123         //@cond
124         typedef details::make_iterable_list< GC, T, Traits > maker;
125         typedef typename maker::type base_class;
126         //@endcond
127
128     public:
129         typedef T value_type;   ///< Type of value stored in the list
130         typedef Traits traits;  ///< List traits
131
132         typedef typename base_class::gc             gc;             ///< Garbage collector used
133         typedef typename base_class::back_off       back_off;       ///< Back-off strategy used
134         typedef typename maker::data_allocator_type allocator_type; ///< Allocator type used for allocate/deallocate data
135         typedef typename base_class::item_counter   item_counter;   ///< Item counting policy used
136         typedef typename maker::key_comparator      key_comparator; ///< key comparison functor
137         typedef typename base_class::memory_model   memory_model;   ///< Memory ordering. See \p cds::opt::memory_model option
138         typedef typename base_class::stat           stat;           ///< Internal statistics
139
140         static CDS_CONSTEXPR const size_t c_nHazardPtrCount = base_class::c_nHazardPtrCount; ///< Count of hazard pointer required for the algorithm
141
142         //@cond
143         // Rebind traits (split-list support)
144         template <typename... Options>
145         struct rebind_traits {
146             typedef IterableList<
147                 gc
148                 , value_type
149                 , typename cds::opt::make_options< traits, Options...>::type
150             > type;
151         };
152
153         // Stat selector
154         template <typename Stat>
155         using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >;
156         //@endcond
157
158     protected:
159         //@cond
160         typedef typename maker::cxx_data_allocator  cxx_data_allocator;
161         typedef typename maker::data_disposer       data_disposer;
162         typedef typename base_class::node_type      head_type;
163         //@endcond
164
165     public:
166         /// Guarded pointer
167         typedef typename base_class::guarded_ptr guarded_ptr;
168
169     protected:
170         //@cond
171         template <bool IsConst>
172         class iterator_type: protected base_class::template iterator_type<IsConst>
173         {
174             typedef typename base_class::template iterator_type<IsConst> iterator_base;
175             friend class IterableList;
176
177             iterator_type( iterator_base it )
178                 : iterator_base( it )
179             {}
180
181         public:
182             typedef typename iterator_base::value_ptr value_ptr;
183             typedef typename iterator_base::value_ref value_ref;
184
185             iterator_type()
186             {}
187
188             iterator_type( iterator_type const& src )
189                 : iterator_base( src )
190             {}
191
192             value_ptr operator ->() const
193             {
194                 return iterator_base::operator ->();
195             }
196
197             value_ref operator *() const
198             {
199                 return iterator_base::operator *();
200             }
201
202             /// Pre-increment
203             iterator_type& operator ++()
204             {
205                 iterator_base::operator ++();
206                 return *this;
207             }
208
209             template <bool C>
210             bool operator ==(iterator_type<C> const& i ) const
211             {
212                 return iterator_base::operator ==(i);
213             }
214             template <bool C>
215             bool operator !=(iterator_type<C> const& i ) const
216             {
217                 return iterator_base::operator !=(i);
218             }
219         };
220         //@endcond
221
222     public:
223     ///@name Thread-safe forward iterators
224     //@{
225         /// Forward iterator
226         /**
227             The forward iterator for iterable list has some features:
228             - it has no post-increment operator
229             - to protect the value, the iterator contains a GC-specific guard.
230               For some GC (like as \p gc::HP), a guard is a limited resource per thread, so an exception (or assertion) "no free guard"
231               may be thrown if the limit of guard count per thread is exceeded.
232             - The iterator cannot be moved across thread boundary since it contains thread-private GC's guard.
233             - Iterator is thread-safe: even if an element the iterator points to is removed, the iterator stays valid because
234               it contains the guard keeping the value from to be recycled.
235
236             The iterator interface:
237             \code
238             class iterator {
239             public:
240                 // Default constructor
241                 iterator();
242
243                 // Copy constructor
244                 iterator( iterator const& src );
245
246                 // Dereference operator
247                 value_type * operator ->() const;
248
249                 // Dereference operator
250                 value_type& operator *() const;
251
252                 // Preincrement operator
253                 iterator& operator ++();
254
255                 // Assignment operator
256                 iterator& operator = (iterator const& src);
257
258                 // Equality operators
259                 bool operator ==(iterator const& i ) const;
260                 bool operator !=(iterator const& i ) const;
261             };
262             \endcode
263
264             @note For two iterators pointed to the same element the value can be different;
265             this code
266             \code
267                 if ( it1 == it2 )
268                     assert( &(*it1) == &(*it2));
269             \endcode
270             can throw assertion. The point is that the iterator stores the value of element which can be modified later by other thread.
271             The guard inside the iterator prevents recycling that value so the iterator's value remains valid even after such changing.
272             Other iterator can observe modified value of the element.
273         */
274         typedef iterator_type<false>    iterator;
275
276         /// Const forward iterator
277         /**
278             For iterator's features and requirements see \ref iterator
279         */
280         typedef iterator_type<true>     const_iterator;
281
282         /// Returns a forward iterator addressing the first element in a list
283         /**
284             For empty list \code begin() == end() \endcode
285         */
286         iterator begin()
287         {
288             return iterator( base_class::begin());
289         }
290
291         /// Returns an iterator that addresses the location succeeding the last element in a list
292         /**
293             Do not use the value returned by <tt>end</tt> function to access any item.
294             Internally, <tt>end</tt> returning value equals to \p nullptr.
295
296             The returned value can be used only to control reaching the end of the list.
297             For empty list \code begin() == end() \endcode
298         */
299         iterator end()
300         {
301             return iterator( base_class::end());
302         }
303
304         /// Returns a forward const iterator addressing the first element in a list
305         const_iterator begin() const
306         {
307             return const_iterator( base_class::cbegin());
308         }
309
310         /// Returns a forward const iterator addressing the first element in a list
311         const_iterator cbegin() const
312         {
313             return const_iterator( base_class::cbegin());
314         }
315
316         /// Returns an const iterator that addresses the location succeeding the last element in a list
317         const_iterator end() const
318         {
319             return const_iterator( base_class::cend());
320         }
321
322         /// Returns an const iterator that addresses the location succeeding the last element in a list
323         const_iterator cend() const
324         {
325             return const_iterator( base_class::cend());
326         }
327     //@}
328
329     public:
330         /// Default constructor
331         /**
332             Initialize empty list
333         */
334         IterableList()
335         {}
336
337         //@cond
338         template <typename Stat, typename = std::enable_if<std::is_same<stat, iterable_list::wrapped_stat<Stat>>::value >>
339         explicit IterableList( Stat& st )
340             : base_class( st )
341         {}
342         //@endcond
343
344         /// List destructor
345         /**
346             Clears the list
347         */
348         ~IterableList()
349         {}
350
351         /// Inserts new node
352         /**
353             The function creates a node with copy of \p val value
354             and then inserts the node created into the list.
355
356             The type \p Q should contain least the complete key of the node.
357             The object of \ref value_type should be constructible from \p val of type \p Q.
358             In trivial case, \p Q is equal to \ref value_type.
359
360             Returns \p true if inserting successful, \p false otherwise.
361         */
362         template <typename Q>
363         bool insert( Q&& val )
364         {
365             return insert_at( head(), std::forward<Q>( val ));
366         }
367
368         /// Inserts new node
369         /**
370             This function inserts new node with default-constructed value and then it calls
371             \p func functor with signature
372             \code
373             void func( value_type& data );
374             \endcode
375
376             The argument \p data of user-defined functor \p func is the reference
377             to the list's item inserted. User-defined functor \p func should guarantee that during changing
378             item's value no any other changes could be made on this list's item by concurrent threads.
379             The user-defined functor is called only if inserting is success.
380
381             The type \p Q should contain the complete key of the node.
382             The object of \p value_type should be constructible from \p key of type \p Q.
383
384             The function allows to split creating of new item into two part:
385             - create item from \p key with initializing key-fields only;
386             - insert new item into the list;
387             - if inserting is successful, initialize non-key fields of item by calling \p func functor
388
389             The method can be useful if complete initialization of object of \p value_type is heavyweight and
390             it is preferable that the initialization should be completed only if inserting is successful.
391
392             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
393         */
394         template <typename Q, typename Func>
395         bool insert( Q&& key, Func func )
396         {
397             return insert_at( head(), std::forward<Q>( key ), func );
398         }
399
400         /// Updates data by \p key
401         /**
402             The operation performs inserting or replacing the element with lock-free manner.
403
404             If the \p key not found in the list, then the new item created from \p key
405             will be inserted iff \p bAllowInsert is \p true.
406             Otherwise, if \p key is found, the functor \p func is called with item found.
407
408             The functor \p func is called after inserting or replacing, it signature is:
409             \code
410                 void func( value_type& val, value_type * old );
411             \endcode
412             where
413             - \p val - a new data constructed from \p key
414             - \p old - old value that will be retired. If new item has been inserted then \p old is \p nullptr.
415
416             The functor may change non-key fields of \p val; however, \p func must guarantee
417             that during changing no any other modifications could be made on this item by concurrent threads.
418
419             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
420             \p second is true if new item has been added or \p false if the item with such \p key
421             already exists.
422
423             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
424         */
425         template <typename Q, typename Func>
426         std::pair<bool, bool> update( Q&& key, Func func, bool bAllowInsert = true )
427         {
428             return update_at( head(), std::forward<Q>( key ), func, bAllowInsert );
429         }
430
431         /// Insert or update
432         /**
433             The operation performs inserting or updating data with lock-free manner.
434
435             If the item \p key is not found in the list, then \p key is inserted
436             iff \p bInsert is \p true.
437             Otherwise, the current element is changed to \p key, the old element will be retired later.
438
439             \p value_type should be constructible from \p key.
440
441             Returns std::pair<bool, bool> where \p first is \p true if operation is successful,
442             \p second is \p true if \p key has been added or \p false if the item with that key
443             already in the list.
444         */
445         template <typename Q>
446         std::pair<bool, bool> upsert( Q&& key, bool bInsert = true )
447         {
448             return update_at( head(), std::forward<Q>( key ), []( value_type&, value_type* ) {}, bInsert );
449         }
450
451         /// Inserts data of type \p value_type constructed with <tt>std::forward<Args>(args)...</tt>
452         /**
453             Returns \p true if inserting successful, \p false otherwise.
454         */
455         template <typename... Args>
456         bool emplace( Args&&... args )
457         {
458             return emplace_at( head(), std::forward<Args>(args)... );
459         }
460
461         /// Delete \p key from the list
462         /**
463             Since the key of IterableList's item type \p value_type is not explicitly specified,
464             template parameter \p Q sould contain the complete key to search in the list.
465             The list item comparator should be able to compare the type \p value_type
466             and the type \p Q.
467
468             Return \p true if key is found and deleted, \p false otherwise
469         */
470         template <typename Q>
471         bool erase( Q const& key )
472         {
473             return erase_at( head(), key, key_comparator(), [](value_type const&){} );
474         }
475
476         /// Deletes the item from the list using \p pred predicate for searching
477         /**
478             The function is an analog of \p erase(Q const&) but \p pred is used for key comparing.
479             \p Less functor has the interface like \p std::less.
480             \p pred must imply the same element order as the comparator used for building the list.
481         */
482         template <typename Q, typename Less>
483         bool erase_with( Q const& key, Less pred )
484         {
485             CDS_UNUSED( pred );
486             return erase_at( head(), key, typename maker::template less_wrapper<Less>::type(), [](value_type const&){} );
487         }
488
489         /// Deletes \p key from the list
490         /**
491             The function searches an item with key \p key, calls \p f functor with item found
492             and deletes it. If \p key is not found, the functor is not called.
493
494             The functor \p Func interface:
495             \code
496             struct extractor {
497                 void operator()(const value_type& val) { ... }
498             };
499             \endcode
500
501             Since the key of IterableList's item type \p value_type is not explicitly specified,
502             template parameter \p Q should contain the complete key to search in the list.
503             The list item comparator should be able to compare the type \p value_type of list item
504             and the type \p Q.
505
506             Return \p true if key is found and deleted, \p false otherwise
507         */
508         template <typename Q, typename Func>
509         bool erase( Q const& key, Func f )
510         {
511             return erase_at( head(), key, key_comparator(), f );
512         }
513
514         /// Deletes the item from the list using \p pred predicate for searching
515         /**
516             The function is an analog of \p erase(Q const&, Func) but \p pred is used for key comparing.
517             \p Less functor has the interface like \p std::less.
518             \p pred must imply the same element order as the comparator used for building the list.
519         */
520         template <typename Q, typename Less, typename Func>
521         bool erase_with( Q const& key, Less pred, Func f )
522         {
523             CDS_UNUSED( pred );
524             return erase_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
525         }
526
527         /// Deletes the item pointed by iterator \p iter
528         /**
529             Returns \p true if the operation is successful, \p false otherwise.
530             The function can return \p false if the node the iterator points to has already been deleted
531             by other thread.
532
533             The function does not invalidate the iterator, it remains valid and can be used for further traversing.
534         */
535         bool erase_at( iterator const& iter )
536         {
537             return base_class::erase_at( iter );
538         }
539
540         /// Extracts the item from the list with specified \p key
541         /**
542             The function searches an item with key equal to \p key,
543             unlinks it from the list, and returns it as \p guarded_ptr.
544             If \p key is not found the function returns an empty guarded pointer.
545
546             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
547
548             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
549
550             Usage:
551             \code
552             typedef cds::container::IterableList< cds::gc::HP, foo, my_traits >  ord_list;
553             ord_list theList;
554             // ...
555             {
556                 ord_list::guarded_ptr gp(theList.extract( 5 ));
557                 if ( gp ) {
558                     // Deal with gp
559                     // ...
560                 }
561                 // Destructor of gp releases internal HP guard and frees the item
562             }
563             \endcode
564         */
565         template <typename Q>
566         guarded_ptr extract( Q const& key )
567         {
568             return extract_at( head(), key, key_comparator());
569         }
570
571         /// Extracts the item from the list with comparing functor \p pred
572         /**
573             The function is an analog of \p extract(Q const&) but \p pred predicate is used for key comparing.
574
575             \p Less functor has the semantics like \p std::less but it should accept arguments
576             of type \p value_type and \p Q in any order.
577             \p pred must imply the same element order as the comparator used for building the list.
578         */
579         template <typename Q, typename Less>
580         guarded_ptr extract_with( Q const& key, Less pred )
581         {
582             CDS_UNUSED( pred );
583             return extract_at( head(), key, typename maker::template less_wrapper<Less>::type());
584         }
585
586         /// Checks whether the list contains \p key
587         /**
588             The function searches the item with key equal to \p key
589             and returns \p true if it is found, and \p false otherwise.
590         */
591         template <typename Q>
592         bool contains( Q const& key ) const
593         {
594             return find_at( head(), key, key_comparator());
595         }
596
597         /// Checks whether the list contains \p key using \p pred predicate for searching
598         /**
599             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
600             \p Less functor has the interface like \p std::less.
601             \p pred must imply the same element order as the comparator used for building the list.
602         */
603         template <typename Q, typename Less>
604         bool contains( Q const& key, Less pred ) const
605         {
606             CDS_UNUSED( pred );
607             return find_at( head(), key, typename maker::template less_wrapper<Less>::type());
608         }
609
610         /// Finds \p key and perform an action with it
611         /**
612             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
613             The interface of \p Func functor is:
614             \code
615             struct functor {
616                 void operator()( value_type& item, Q& key );
617             };
618             \endcode
619             where \p item is the item found, \p key is the <tt>find</tt> function argument.
620
621             The functor may change non-key fields of \p item. Note that the function is only guarantee
622             that \p item cannot be deleted during functor is executing.
623             The function does not serialize simultaneous access to the list \p item. If such access is
624             possible you must provide your own synchronization schema to exclude unsafe item modifications.
625
626             The function returns \p true if \p key is found, \p false otherwise.
627         */
628         template <typename Q, typename Func>
629         bool find( Q& key, Func f ) const
630         {
631             return find_at( head(), key, key_comparator(), f );
632         }
633         //@cond
634         template <typename Q, typename Func>
635         bool find( Q const& key, Func f ) const
636         {
637             return find_at( head(), key, key_comparator(), f );
638         }
639         //@endcond
640
641         /// Finds \p key in the list and returns iterator pointed to the item found
642         /**
643             If \p key is not found the function returns \p end().
644         */
645         template <typename Q>
646         iterator find( Q const& key ) const
647         {
648             return find_iterator_at( head(), key, key_comparator());
649         }
650
651         /// Finds \p key using \p pred predicate for searching
652         /**
653             The function is an analog of \p find(Q&, Func) but \p pred is used for key comparing.
654             \p Less functor has the interface like \p std::less.
655             \p pred must imply the same element order as the comparator used for building the list.
656         */
657         template <typename Q, typename Less, typename Func>
658         bool find_with( Q& key, Less pred, Func f ) const
659         {
660             CDS_UNUSED( pred );
661             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
662         }
663         //@cond
664         template <typename Q, typename Less, typename Func>
665         bool find_with( Q const& key, Less pred, Func f ) const
666         {
667             CDS_UNUSED( pred );
668             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
669         }
670         //@endcond
671
672         /// Finds \p key in the list using \p pred predicate for searching and returns iterator pointed to the item found
673         /**
674             The function is an analog of \p find(Q&) but \p pred is used for key comparing.
675             \p Less functor has the interface like \p std::less.
676             \p pred must imply the same element order as the comparator used for building the list.
677
678             If \p key is not found the function returns \p end().
679         */
680         template <typename Q, typename Less>
681         iterator find_with( Q const& key, Less pred ) const
682         {
683             CDS_UNUSED( pred );
684             return find_iterator_at( head(), key, cds::opt::details::make_comparator_from_less<Less>());
685         }
686
687         /// Finds \p key and return the item found
688         /** \anchor cds_nonintrusive_MichaelList_hp_get
689             The function searches the item with key equal to \p key
690             and returns it as \p guarded_ptr.
691             If \p key is not found the function returns an empty guarded pointer.
692
693             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
694
695             Usage:
696             \code
697             typedef cds::container::MichaelList< cds::gc::HP, foo, my_traits >  ord_list;
698             ord_list theList;
699             // ...
700             {
701                 ord_list::guarded_ptr gp(theList.get( 5 ));
702                 if ( gp ) {
703                     // Deal with gp
704                     //...
705                 }
706                 // Destructor of guarded_ptr releases internal HP guard and frees the item
707             }
708             \endcode
709
710             Note the compare functor specified for class \p Traits template parameter
711             should accept a parameter of type \p Q that can be not the same as \p value_type.
712         */
713         template <typename Q>
714         guarded_ptr get( Q const& key ) const
715         {
716             return get_at( head(), key, key_comparator());
717         }
718
719         /// Finds \p key and return the item found
720         /**
721             The function is an analog of \ref cds_nonintrusive_MichaelList_hp_get "get( Q const&)"
722             but \p pred is used for comparing the keys.
723
724             \p Less functor has the semantics like \p std::less but should accept arguments of type \p value_type and \p Q
725             in any order.
726             \p pred must imply the same element order as the comparator used for building the list.
727         */
728         template <typename Q, typename Less>
729         guarded_ptr get_with( Q const& key, Less pred ) const
730         {
731             CDS_UNUSED( pred );
732             return get_at( head(), key, typename maker::template less_wrapper<Less>::type());
733         }
734
735         /// Checks if the list is empty
736         /**
737             Emptiness is checked by item counting: if item count is zero then the set is empty.
738             Thus, if you need to use \p %empty() you should provide appropriate (non-empty) \p iterable_list::traits::item_counter
739             feature.
740         */
741         bool empty() const
742         {
743             return base_class::empty();
744         }
745
746         /// Returns list's item count
747         /**
748             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
749             this function always returns 0.
750         */
751         size_t size() const
752         {
753             return base_class::size();
754         }
755
756         /// Clears the list (thread safe, not atomic)
757         void clear()
758         {
759             base_class::clear();
760         }
761
762         /// Returns const reference to internal statistics
763         stat const& statistics() const
764         {
765             return base_class::statistics();
766         }
767
768     protected:
769         //@cond
770         template <typename... Args>
771         static value_type* alloc_data( Args&&... args )
772         {
773             return cxx_data_allocator().MoveNew( std::forward<Args>(args)... );
774         }
775
776         static void free_data( value_type* pData )
777         {
778             cxx_data_allocator().Delete( pData );
779         }
780
781         typedef std::unique_ptr< value_type, data_disposer > scoped_data_ptr;
782
783         using base_class::head;
784         //@endcond
785
786     protected:
787         //@cond
788         bool insert_node( value_type* pData )
789         {
790             return insert_node_at( head(), pData );
791         }
792
793         bool insert_node_at( head_type* pHead, value_type* pData )
794         {
795             assert( pData );
796             scoped_data_ptr p( pData );
797             if ( base_class::insert_at( pHead, *pData )) {
798                 p.release();
799                 return true;
800             }
801
802             return false;
803         }
804
805         template <typename Q>
806         bool insert_at( head_type* pHead, Q&& val )
807         {
808             return insert_node_at( pHead, alloc_data( std::forward<Q>( val )));
809         }
810
811         template <typename Q, typename Func>
812         bool insert_at( head_type* pHead, Q&& key, Func f )
813         {
814             scoped_data_ptr pNode( alloc_data( std::forward<Q>( key )));
815
816             if ( base_class::insert_at( pHead, *pNode, f )) {
817                 pNode.release();
818                 return true;
819             }
820             return false;
821         }
822
823         template <typename... Args>
824         bool emplace_at( head_type* pHead, Args&&... args )
825         {
826             return insert_node_at( pHead, alloc_data( std::forward<Args>(args)... ));
827         }
828
829         template <typename Q, typename Func>
830         std::pair<bool, bool> update_at( head_type* pHead, Q&& key, Func f, bool bAllowInsert )
831         {
832             scoped_data_ptr pData( alloc_data( std::forward<Q>( key )));
833
834             std::pair<bool, bool> ret = base_class::update_at( pHead, *pData, f, bAllowInsert );
835             if ( ret.first )
836                 pData.release();
837
838             return ret;
839         }
840
841         template <typename Q, typename Compare, typename Func>
842         bool erase_at( head_type* pHead, Q const& key, Compare cmp, Func f )
843         {
844             return base_class::erase_at( pHead, key, cmp, f );
845         }
846
847         template <typename Q, typename Compare>
848         guarded_ptr extract_at( head_type* pHead, Q const& key, Compare cmp )
849         {
850             return base_class::extract_at( pHead, key, cmp );
851         }
852
853         template <typename Q, typename Compare>
854         bool find_at( head_type const* pHead, Q const& key, Compare cmp ) const
855         {
856             return base_class::find_at( pHead, key, cmp );
857         }
858
859         template <typename Q, typename Compare, typename Func>
860         bool find_at( head_type const* pHead, Q& val, Compare cmp, Func f ) const
861         {
862             return base_class::find_at( pHead, val, cmp, f );
863         }
864
865         template <typename Q, typename Compare>
866         iterator find_iterator_at( head_type const* pHead, Q const& key, Compare cmp ) const
867         {
868             return iterator( base_class::find_iterator_at( pHead, key, cmp ));
869         }
870
871         template <typename Q, typename Compare>
872         guarded_ptr get_at( head_type const* pHead, Q const& key, Compare cmp ) const
873         {
874             return base_class::get_at( pHead, key, cmp );
875         }
876         //@endcond
877     };
878
879 }}  // namespace cds::container
880
881 #endif  // #ifndef CDSLIB_CONTAINER_IMPL_ITERABLE_LIST_H