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