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