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