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