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