Removed redundant spaces
[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         //@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         /// Extracts the item from the list with specified \p key
528         /**
529             The function searches an item with key equal to \p key,
530             unlinks it from the list, and returns it as \p guarded_ptr.
531             If \p key is not found the function returns an empty guarded pointer.
532
533             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
534
535             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
536
537             Usage:
538             \code
539             typedef cds::container::IterableList< cds::gc::HP, foo, my_traits >  ord_list;
540             ord_list theList;
541             // ...
542             {
543                 ord_list::guarded_ptr gp(theList.extract( 5 ));
544                 if ( gp ) {
545                     // Deal with gp
546                     // ...
547                 }
548                 // Destructor of gp releases internal HP guard and frees the item
549             }
550             \endcode
551         */
552         template <typename Q>
553         guarded_ptr extract( Q const& key )
554         {
555             return extract_at( head(), key, key_comparator());
556         }
557
558         /// Extracts the item from the list with comparing functor \p pred
559         /**
560             The function is an analog of \p extract(Q const&) but \p pred predicate is used for key comparing.
561
562             \p Less functor has the semantics like \p std::less but it should accept arguments
563             of type \p value_type and \p Q in any order.
564             \p pred must imply the same element order as the comparator used for building the list.
565         */
566         template <typename Q, typename Less>
567         guarded_ptr extract_with( Q const& key, Less pred )
568         {
569             CDS_UNUSED( pred );
570             return extract_at( head(), key, typename maker::template less_wrapper<Less>::type());
571         }
572
573         /// Checks whether the list contains \p key
574         /**
575             The function searches the item with key equal to \p key
576             and returns \p true if it is found, and \p false otherwise.
577         */
578         template <typename Q>
579         bool contains( Q const& key ) const
580         {
581             return find_at( head(), key, key_comparator());
582         }
583
584         /// Checks whether the list contains \p key using \p pred predicate for searching
585         /**
586             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
587             \p Less functor has the interface like \p std::less.
588             \p pred must imply the same element order as the comparator used for building the list.
589         */
590         template <typename Q, typename Less>
591         bool contains( Q const& key, Less pred ) const
592         {
593             CDS_UNUSED( pred );
594             return find_at( head(), key, typename maker::template less_wrapper<Less>::type());
595         }
596
597         /// Finds \p key and perform an action with it
598         /**
599             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
600             The interface of \p Func functor is:
601             \code
602             struct functor {
603                 void operator()( value_type& item, Q& key );
604             };
605             \endcode
606             where \p item is the item found, \p key is the <tt>find</tt> function argument.
607
608             The functor may change non-key fields of \p item. Note that the function is only guarantee
609             that \p item cannot be deleted during functor is executing.
610             The function does not serialize simultaneous access to the list \p item. If such access is
611             possible you must provide your own synchronization schema to exclude unsafe item modifications.
612
613             The function returns \p true if \p key is found, \p false otherwise.
614         */
615         template <typename Q, typename Func>
616         bool find( Q& key, Func f ) const
617         {
618             return find_at( head(), key, key_comparator(), f );
619         }
620         //@cond
621         template <typename Q, typename Func>
622         bool find( Q const& key, Func f ) const
623         {
624             return find_at( head(), key, key_comparator(), f );
625         }
626         //@endcond
627
628         /// Finds \p key in the list and returns iterator pointed to the item found
629         /**
630             If \p key is not found the function returns \p end().
631         */
632         template <typename Q>
633         iterator find( Q const& key ) const
634         {
635             return find_iterator_at( head(), key, key_comparator());
636         }
637
638         /// Finds \p key using \p pred predicate for searching
639         /**
640             The function is an analog of \p find(Q&, Func) but \p pred is used for key comparing.
641             \p Less functor has the interface like \p std::less.
642             \p pred must imply the same element order as the comparator used for building the list.
643         */
644         template <typename Q, typename Less, typename Func>
645         bool find_with( Q& key, Less pred, Func f ) const
646         {
647             CDS_UNUSED( pred );
648             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
649         }
650         //@cond
651         template <typename Q, typename Less, typename Func>
652         bool find_with( Q const& key, Less pred, Func f ) const
653         {
654             CDS_UNUSED( pred );
655             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
656         }
657         //@endcond
658
659         /// Finds \p key in the list using \p pred predicate for searching and returns iterator pointed to the item found
660         /**
661             The function is an analog of \p find(Q&) but \p pred is used for key comparing.
662             \p Less functor has the interface like \p std::less.
663             \p pred must imply the same element order as the comparator used for building the list.
664
665             If \p key is not found the function returns \p end().
666         */
667         template <typename Q, typename Less>
668         iterator find_with( Q const& key, Less pred ) const
669         {
670             CDS_UNUSED( pred );
671             return find_iterator_at( head(), key, cds::opt::details::make_comparator_from_less<Less>());
672         }
673
674         /// Finds \p key and return the item found
675         /** \anchor cds_nonintrusive_MichaelList_hp_get
676             The function searches the item with key equal to \p key
677             and returns it as \p guarded_ptr.
678             If \p key is not found the function returns an empty guarded pointer.
679
680             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
681
682             Usage:
683             \code
684             typedef cds::container::MichaelList< cds::gc::HP, foo, my_traits >  ord_list;
685             ord_list theList;
686             // ...
687             {
688                 ord_list::guarded_ptr gp(theList.get( 5 ));
689                 if ( gp ) {
690                     // Deal with gp
691                     //...
692                 }
693                 // Destructor of guarded_ptr releases internal HP guard and frees the item
694             }
695             \endcode
696
697             Note the compare functor specified for class \p Traits template parameter
698             should accept a parameter of type \p Q that can be not the same as \p value_type.
699         */
700         template <typename Q>
701         guarded_ptr get( Q const& key ) const
702         {
703             return get_at( head(), key, key_comparator());
704         }
705
706         /// Finds \p key and return the item found
707         /**
708             The function is an analog of \ref cds_nonintrusive_MichaelList_hp_get "get( Q const&)"
709             but \p pred is used for comparing the keys.
710
711             \p Less functor has the semantics like \p std::less but should accept arguments of type \p value_type and \p Q
712             in any order.
713             \p pred must imply the same element order as the comparator used for building the list.
714         */
715         template <typename Q, typename Less>
716         guarded_ptr get_with( Q const& key, Less pred ) const
717         {
718             CDS_UNUSED( pred );
719             return get_at( head(), key, typename maker::template less_wrapper<Less>::type());
720         }
721
722         /// Checks if the list is empty
723         /**
724             Emptiness is checked by item counting: if item count is zero then the set is empty.
725             Thus, if you need to use \p %empty() you should provide appropriate (non-empty) \p iterable_list::traits::item_counter
726             feature.
727         */
728         bool empty() const
729         {
730             return base_class::empty();
731         }
732
733         /// Returns list's item count
734         /**
735             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
736             this function always returns 0.
737         */
738         size_t size() const
739         {
740             return base_class::size();
741         }
742
743         /// Clears the list (thread safe, not atomic)
744         void clear()
745         {
746             base_class::clear();
747         }
748
749         /// Returns const reference to internal statistics
750         stat const& statistics() const
751         {
752             return base_class::statistics();
753         }
754
755     protected:
756         //@cond
757         template <typename... Args>
758         static value_type* alloc_data( Args&&... args )
759         {
760             return cxx_data_allocator().MoveNew( std::forward<Args>(args)... );
761         }
762
763         static void free_data( value_type* pData )
764         {
765             cxx_data_allocator().Delete( pData );
766         }
767
768         typedef std::unique_ptr< value_type, data_disposer > scoped_data_ptr;
769
770         using base_class::head;
771         //@endcond
772
773     protected:
774         //@cond
775         bool insert_node( value_type* pData )
776         {
777             return insert_node_at( head(), pData );
778         }
779
780         bool insert_node_at( head_type* pHead, value_type* pData )
781         {
782             assert( pData );
783             scoped_data_ptr p( pData );
784             if ( base_class::insert_at( pHead, *pData )) {
785                 p.release();
786                 return true;
787             }
788
789             return false;
790         }
791
792         template <typename Q>
793         bool insert_at( head_type* pHead, Q&& val )
794         {
795             return insert_node_at( pHead, alloc_data( std::forward<Q>( val )));
796         }
797
798         template <typename Q, typename Func>
799         bool insert_at( head_type* pHead, Q&& key, Func f )
800         {
801             scoped_data_ptr pNode( alloc_data( std::forward<Q>( key )));
802
803             if ( base_class::insert_at( pHead, *pNode, f )) {
804                 pNode.release();
805                 return true;
806             }
807             return false;
808         }
809
810         template <typename... Args>
811         bool emplace_at( head_type* pHead, Args&&... args )
812         {
813             return insert_node_at( pHead, alloc_data( std::forward<Args>(args)... ));
814         }
815
816         template <typename Q, typename Func>
817         std::pair<bool, bool> update_at( head_type* pHead, Q&& key, Func f, bool bAllowInsert )
818         {
819             scoped_data_ptr pData( alloc_data( std::forward<Q>( key )));
820
821             std::pair<bool, bool> ret = base_class::update_at( pHead, *pData, f, bAllowInsert );
822             if ( ret.first )
823                 pData.release();
824
825             return ret;
826         }
827
828         template <typename Q, typename Compare, typename Func>
829         bool erase_at( head_type* pHead, Q const& key, Compare cmp, Func f )
830         {
831             return base_class::erase_at( pHead, key, cmp, f );
832         }
833
834         template <typename Q, typename Compare>
835         guarded_ptr extract_at( head_type* pHead, Q const& key, Compare cmp )
836         {
837             return base_class::extract_at( pHead, key, cmp );
838         }
839
840         template <typename Q, typename Compare>
841         bool find_at( head_type const* pHead, Q const& key, Compare cmp ) const
842         {
843             return base_class::find_at( pHead, key, cmp );
844         }
845
846         template <typename Q, typename Compare, typename Func>
847         bool find_at( head_type const* pHead, Q& val, Compare cmp, Func f ) const
848         {
849             return base_class::find_at( pHead, val, cmp, f );
850         }
851
852         template <typename Q, typename Compare>
853         iterator find_iterator_at( head_type const* pHead, Q const& key, Compare cmp ) const
854         {
855             return iterator( base_class::find_iterator_at( pHead, key, cmp ));
856         }
857
858         template <typename Q, typename Compare>
859         guarded_ptr get_at( head_type const* pHead, Q const& key, Compare cmp ) const
860         {
861             return base_class::get_at( pHead, key, cmp );
862         }
863         //@endcond
864     };
865
866 }}  // namespace cds::container
867
868 #endif  // #ifndef CDSLIB_CONTAINER_IMPL_ITERABLE_LIST_H