aaad301e17d8d31f4452f6e109f05252b5878d10
[libcds.git] / cds / container / impl / iterable_kvlist.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_KVLIST_H
32 #define CDSLIB_CONTAINER_IMPL_ITERABLE_KVLIST_H
33
34 #include <memory>
35 #include <cds/container/details/guarded_ptr_cast.h>
36
37 namespace cds { namespace container {
38
39     /// Iterable ordered list for key-value pair
40     /** @ingroup cds_nonintrusive_list
41         \anchor cds_nonintrusive_IterableKVList_gc
42
43         This is key-value variation of non-intrusive \p IterableList.
44         Like standard container, this implementation split a value stored into two part -
45         constant key and alterable value.
46
47         Usually, ordered single-linked list is used as a building block for the hash table implementation.
48         Iterable list is suitable for almost append-only hash table because the list doesn't delete
49         its internal node when erasing a key but it is marked them as empty to be reused in the future.
50         However, plenty of empty nodes degrades performance. 
51         
52         The complexity of searching is <tt>O(N)</tt>.
53
54         Template arguments:
55         - \p GC - garbage collector used
56         - \p Key - key type of an item stored in the list. It should be copy-constructible
57         - \p Value - value type stored in a list
58         - \p Traits - type traits, default is \p iterable_list::traits
59
60         It is possible to declare option-based list with \p cds::container::iterable_list::make_traits metafunction instead of \p Traits template
61         argument. For example, the following traits-based declaration of \p gc::HP iterable list
62         \code
63         #include <cds/container/iterable_kvlist_hp.h>
64         // Declare comparator for the item
65         struct my_compare {
66             int operator ()( int i1, int i2 )
67             {
68                 return i1 - i2;
69             }
70         };
71
72         // Declare traits
73         struct my_traits: public cds::container::iterable_list::traits
74         {
75             typedef my_compare compare;
76         };
77
78         // Declare traits-based list
79         typedef cds::container::IterableKVList< cds::gc::HP, int, int, my_traits > traits_based_list;
80         \endcode
81         is equivalent for the following option-based list
82         \code
83         #include <cds/container/iterable_kvlist_hp.h>
84
85         // my_compare is the same
86
87         // Declare option-based list
88         typedef cds::container::IterableKVList< cds::gc::HP, int, int,
89             typename cds::container::iterable_list::make_traits<
90                 cds::container::opt::compare< my_compare >     // item comparator option
91             >::type
92         >     option_based_list;
93         \endcode
94
95         \par Usage
96         There are different specializations of this template for each garbage collecting schema used.
97         You should include appropriate .h-file depending on GC you are using:
98         - for gc::HP: \code #include <cds/container/iterable_kvlist_hp.h> \endcode
99         - for gc::DHP: \code #include <cds/container/iterable_kvlist_dhp.h> \endcode
100         - for \ref cds_urcu_desc "RCU": \code #include <cds/container/iterable_kvlist_rcu.h> \endcode
101     */
102     template <
103         typename GC,
104         typename Key,
105         typename Value,
106 #ifdef CDS_DOXYGEN_INVOKED
107         typename Traits = iterable_list::traits
108 #else
109         typename Traits
110 #endif
111     >
112     class IterableKVList:
113 #ifdef CDS_DOXYGEN_INVOKED
114         protected container::IterableList< GC, std::pair<Key, Value>, Traits >
115 #else
116         protected details::make_iterable_kvlist< GC, Key, Value, Traits >::type
117 #endif
118     {
119         //@cond
120         typedef details::make_iterable_kvlist< GC, Key, Value, Traits > maker;
121         typedef typename maker::type base_class;
122         //@endcond
123
124     public:
125 #ifdef CDS_DOXYGEN_INVOKED
126         typedef Key                                 key_type;      ///< Key type
127         typedef Value                               mapped_type;   ///< Type of value stored in the list
128         typedef std::pair<key_type const, mapped_type> value_type; ///< key/value pair stored in the list
129 #else
130         typedef typename maker::key_type    key_type;
131         typedef typename maker::mapped_type mapped_type;
132         typedef typename maker::value_type  value_type;
133 #endif
134
135         typedef typename base_class::gc           gc;             ///< Garbage collector used
136         typedef typename base_class::back_off     back_off;       ///< Back-off strategy used
137         typedef typename maker::data_allocator_type allocator_type; ///< Allocator type used for allocate/deallocate data
138         typedef typename base_class::item_counter item_counter;   ///< Item counting policy used
139         typedef typename maker::key_comparator    key_comparator; ///< key comparison functor
140         typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See cds::opt::memory_model option
141         typedef typename base_class::stat         stat;           ///< Internal statistics
142
143         static CDS_CONSTEXPR const size_t c_nHazardPtrCount = base_class::c_nHazardPtrCount; ///< Count of hazard pointer required for the algorithm
144
145         /// Guarded pointer
146         typedef typename base_class::guarded_ptr guarded_ptr;
147
148     protected:
149         //@cond
150         typedef typename base_class::head_type     head_type;
151         typedef typename maker::cxx_data_allocator cxx_data_allocator;
152
153         template <typename Less>
154         using less_wrapper = typename maker::template less_wrapper< Less >;
155
156         template <bool IsConst>
157         using iterator_type = typename base_class::template iterator_type<IsConst>;
158         //@endcond
159
160     public:
161         /// Forward iterator
162         /**
163             The forward iterator for iterable list has some features:
164             - it has no post-increment operator
165             - to protect the value, the iterator contains a GC-specific guard.
166               For some GC (like as \p gc::HP), a guard is a limited resource per thread, so an exception (or assertion) "no free guard"
167               may be thrown if the limit of guard count per thread is exceeded.
168             - The iterator cannot be moved across thread boundary since it contains thread-private GC's guard.
169             - Iterator is thread-safe: even if an element the iterator points to is removed, the iterator stays valid because
170               it contains the guard keeping the value from to be recycled.
171
172             The iterator interface:
173             \code
174             class iterator {
175             public:
176                 // Default constructor
177                 iterator();
178
179                 // Copy constructor
180                 iterator( iterator const& src );
181
182                 // Dereference operator
183                 value_type * operator ->() const;
184
185                 // Dereference operator
186                 value_type& operator *() const;
187
188                 // Preincrement operator
189                 iterator& operator ++();
190
191                 // Assignment operator
192                 iterator& operator = (iterator const& src);
193
194                 // Equality operators
195                 bool operator ==(iterator const& i ) const;
196                 bool operator !=(iterator const& i ) const;
197             };
198             \endcode
199
200             @note For two iterators pointed to the same element the value can be different;
201             this code
202             \code
203                 if ( it1 == it2 )
204                     assert( &(*it1) == &(*it2) );
205             \endcode
206             can throw assertion. The point is that the iterator stores the value of element which can be modified later by other thread.
207             The guard inside the iterator prevents recycling that value so the iterator's value remains valid even after such changing.
208             Other iterator can observe modified value of the element.
209         */
210         using typename base_class::iterator;
211         using typename base_class::const_iterator;
212         using base_class::begin;
213         using base_class::end;
214         using base_class::cbegin;
215         using base_class::cend;
216
217     public:
218         /// Default constructor
219         /**
220             Initializes empty list
221         */
222         IterableKVList()
223         {}
224
225         //@cond
226         template <typename Stat, typename = std::enable_if<std::is_same<stat, iterable_list::wrapped_stat<Stat>>::value >>
227         explicit IterableKVList( Stat& st )
228             : base_class( st )
229         {}
230         //@endcond
231
232         /// List destructor
233         /**
234             Clears the list
235         */
236         ~IterableKVList()
237         {}
238
239         /// Inserts new node with key and default value
240         /**
241             The function creates a node with \p key and default value, and then inserts the node created into the list.
242
243             Preconditions:
244             - The \p key_type should be constructible from value of type \p K. In trivial case, \p K is equal to \p key_type.
245             - The \p mapped_type should be default-constructible.
246
247             Returns \p true if inserting successful, \p false otherwise.
248
249             @note The function is supported only if \ref mapped_type is default constructible
250         */
251         template <typename K>
252         bool insert( K const& key )
253         {
254             return base_class::emplace( key, mapped_type());
255         }
256
257         /// Inserts new node with a key and a value
258         /**
259             The function creates a node with \p key and value \p val, and then inserts the node created into the list.
260
261             Preconditions:
262             - The \p key_type should be constructible from \p key of type \p K.
263             - The \p mapped_type should be constructible from \p val of type \p V.
264
265             Returns \p true if inserting successful, \p false otherwise.
266         */
267         template <typename K, typename V>
268         bool insert( K const& key, V const& val )
269         {
270             return base_class::emplace( key, val );
271         }
272
273         /// Inserts new node and initialize it by a functor
274         /**
275             This function inserts new node with key \p key and if inserting is successful then it calls
276             \p func functor with signature
277             \code
278                 struct functor {
279                     void operator()( value_type& item );
280                 };
281             \endcode
282
283             The argument \p item of user-defined functor \p func is the reference
284             to the item inserted. <tt>item.second</tt> is a reference to item's value that may be changed.
285             User-defined functor \p func should guarantee that during changing item's value no any other changes
286             could be made on this list's item by concurrent threads.
287             The user-defined functor is called only if inserting is successful.
288
289             The \p key_type should be constructible from value of type \p K.
290
291             The function allows to split creating of new item into two part:
292             - create a new item from \p key;
293             - insert the new item into the list;
294             - if inserting is successful, initialize the value of item by calling \p func functor
295
296             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
297             it is preferable that the initialization should be completed only if inserting is successful.
298
299             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
300
301             @note The function is supported only if \ref mapped_type is default constructible
302         */
303         template <typename K, typename Func>
304         bool insert_with( K const& key, Func func )
305         {
306             return base_class::insert( value_type( key_type( key ), mapped_type()), func );
307         }
308
309         /// Updates data by \p key
310         /**
311             The operation performs inserting or replacing the element with lock-free manner.
312
313             If the \p key not found in the list, then the new item created from \p key
314             will be inserted iff \p bAllowInsert is \p true.
315             (note that in this case the \ref key_type should be constructible from type \p K).
316             Otherwise, if \p key is found, the functor \p func is called with item found.
317
318             The functor \p func is called after inserting or replacing, it signature is:
319             \code
320                 void func( value_type& val, value_type* old );
321             \endcode
322             where
323             - \p val - a new data constructed from \p key
324             - \p old - old value that will be retired. If new item has been inserted then \p old is \p nullptr.
325
326             The functor may change non-key fields of \p val; however, \p func must guarantee
327             that during changing no any other modifications could be made on this item by concurrent threads.
328
329             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
330             \p second is true if new item has been added or \p false if the item with such \p key
331             already exists.
332
333             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
334
335             @note The function is supported only if \ref mapped_type is default constructible
336         */
337         template <typename K, typename Func>
338         std::pair<bool, bool> update( K const& key, Func f, bool bAllowInsert = true )
339         {
340             return base_class::update( value_type( key_type( key ), mapped_type()), f, bAllowInsert );
341         }
342
343         /// Insert or update
344         /**
345             The operation performs inserting or updating data with lock-free manner.
346
347             If the item \p key is not found in the list, then \p key is inserted
348             iff \p bInsert is \p true.
349             Otherwise, the current element is changed to <tt> value_type( key, val )</tt>, 
350             the old element will be retired later.
351
352             Returns std::pair<bool, bool> where \p first is \p true if operation is successful,
353             \p second is \p true if \p key has been added or \p false if the item with that key
354             already in the list.
355         */
356         template <typename Q, typename V >
357         std::pair<bool, bool> upsert( Q&& key, V&& val, bool bInsert = true )
358         {
359             return base_class::upsert( value_type( key_type( std::forward<Q>( key )), mapped_type( std::forward<V>( val ))), bInsert );
360         }
361
362         /// Inserts a new node using move semantics
363         /**
364             \p key_type field of new item is constructed from \p key argument,
365             \p mapped_type field is done from \p args.
366
367             Returns \p true if inserting successful, \p false otherwise.
368         */
369         template <typename K, typename... Args>
370         bool emplace( K&& key, Args&&... args )
371         {
372             return base_class::emplace( std::forward<K>( key ), std::forward<Args>( args )... );
373         }
374
375         /// Deletes \p key from the list
376         /**
377
378             Returns \p true if \p key is found and has been deleted, \p false otherwise
379         */
380         template <typename K>
381         bool erase( K const& key )
382         {
383             return base_class::erase( key );
384         }
385
386         /// Deletes the item from the list using \p pred predicate for searching
387         /**
388             The function is an analog of \p erase(K const&) but \p pred is used for key comparing.
389             \p Less functor has the interface like \p std::less.
390             \p pred must imply the same element order as the comparator used for building the list.
391         */
392         template <typename K, typename Less>
393         bool erase_with( K const& key, Less pred )
394         {
395             CDS_UNUSED( pred );
396             return base_class::erase_with( key, less_wrapper<Less>() );
397         }
398
399         /// Deletes \p key from the list
400         /**
401             The function searches an item with key \p key, calls \p f functor
402             and deletes the item. If \p key is not found, the functor is not called.
403
404             The functor \p Func interface:
405             \code
406             struct extractor {
407                 void operator()(value_type& val) { ... }
408             };
409             \endcode
410
411             Return \p true if key is found and deleted, \p false otherwise
412         */
413         template <typename K, typename Func>
414         bool erase( K const& key, Func f )
415         {
416             return base_class::erase( key, f );
417         }
418
419         /// Deletes the item from the list using \p pred predicate for searching
420         /**
421             The function is an analog of \p erase(K const&, Func) but \p pred is used for key comparing.
422             \p Less functor has the interface like \p std::less.
423             \p pred must imply the same element order as the comparator used for building the list.
424         */
425         template <typename K, typename Less, typename Func>
426         bool erase_with( K const& key, Less pred, Func f )
427         {
428             CDS_UNUSED( pred );
429             return base_class::erase_with( key, less_wrapper<Less>(), f );
430         }
431
432         /// Extracts the item from the list with specified \p key
433         /**
434             The function searches an item with key equal to \p key,
435             unlinks it from the list, and returns it as \p guarded_ptr.
436             If \p key is not found the function returns an empty guarded pointer.
437
438             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
439
440             The \p disposer specified in \p Traits class template parameter is called automatically
441             by garbage collector \p GC specified in class' template parameters when returned \p guarded_ptr object
442             will be destroyed or released.
443             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
444
445             Usage:
446             \code
447             typedef cds::container::IterableKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
448             ord_list theList;
449             // ...
450             {
451                 ord_list::guarded_ptr gp(theList.extract( 5 ));
452                 if ( gp ) {
453                     // Deal with gp
454                     // ...
455                 }
456                 // Destructor of gp releases internal HP guard
457             }
458             \endcode
459         */
460         template <typename K>
461         guarded_ptr extract( K const& key )
462         {
463             return base_class::extract( key );
464         }
465
466         /// Extracts the item from the list with comparing functor \p pred
467         /**
468             The function is an analog of \p extract(K const&) but \p pred predicate is used for key comparing.
469
470             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
471             in any order.
472             \p pred must imply the same element order as the comparator used for building the list.
473         */
474         template <typename K, typename Less>
475         guarded_ptr extract_with( K const& key, Less pred )
476         {
477             CDS_UNUSED( pred );
478             return base_class::extract_with( key, less_wrapper<Less>() );
479         }
480
481         /// Checks whether the list contains \p key
482         /**
483             The function searches the item with key equal to \p key
484             and returns \p true if it is found, and \p false otherwise.
485         */
486         template <typename Q>
487         bool contains( Q const& key ) const
488         {
489             return base_class::contains( key );
490         }
491
492         /// Checks whether the map contains \p key using \p pred predicate for searching
493         /**
494             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
495             \p Less functor has the interface like \p std::less.
496             \p Less must imply the same element order as the comparator used for building the list.
497         */
498         template <typename Q, typename Less>
499         bool contains( Q const& key, Less pred ) const
500         {
501             CDS_UNUSED( pred );
502             return base_class::contains( key, less_wrapper<Less>() );
503         }
504
505         /// Finds the key \p key and performs an action with it
506         /**
507             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
508             The interface of \p Func functor is:
509             \code
510             struct functor {
511                 void operator()( value_type& item );
512             };
513             \endcode
514             where \p item is the item found.
515
516             The functor may change <tt>item.second</tt> that is reference to value of node.
517             Note that the function is only guarantee that \p item cannot be deleted during functor is executing.
518             The function does not serialize simultaneous access to the list \p item. If such access is
519             possible you must provide your own synchronization schema to exclude unsafe item modifications.
520
521             The function returns \p true if \p key is found, \p false otherwise.
522         */
523         template <typename Q, typename Func>
524         bool find( Q const& key, Func f ) const
525         {
526             return base_class::find( key, [&f]( value_type& v, Q const& ) { f( v ); } );
527         }
528
529         /// Finds \p key in the list and returns iterator pointed to the item found
530         /**
531             If \p key is not found the function returns \p end().
532         */
533         template <typename Q>
534         iterator find( Q const& key ) const
535         {
536             return base_class::find( key );
537         }
538
539         /// Finds the key \p val using \p pred predicate for searching
540         /**
541             The function is an analog of \p find(Q&, Func) but \p pred is used for key comparing.
542             \p Less functor has the interface like \p std::less.
543             \p pred must imply the same element order as the comparator used for building the list.
544         */
545         template <typename Q, typename Less, typename Func>
546         bool find_with( Q const& key, Less pred, Func f ) const
547         {
548             CDS_UNUSED( pred );
549             return base_class::find_with( key, less_wrapper<Less>(), [&f]( value_type& v, Q const& ) { f( v ); } );
550         }
551
552         /// Finds \p key in the list using \p pred predicate for searching and returns iterator pointed to the item found
553         /**
554             The function is an analog of \p find(Q&) but \p pred is used for key comparing.
555             \p Less functor has the interface like \p std::less.
556             \p pred must imply the same element order as the comparator used for building the list.
557
558             If \p key is not found the function returns \p end().
559         */
560         template <typename Q, typename Less>
561         iterator find_with( Q const& key, Less pred ) const
562         {
563             CDS_UNUSED( pred );
564             return base_class::find_with( key, less_wrapper<Less>());
565         }
566
567         /// Finds the \p key and return the item found
568         /**
569             The function searches the item with key equal to \p key
570             and returns it as \p guarded_ptr.
571             If \p key is not found the function returns an empty guarded pointer.
572
573             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
574
575             Usage:
576             \code
577             typedef cds::container::IterableKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
578             ord_list theList;
579             // ...
580             {
581                 ord_list::guarded_ptr gp(theList.get( 5 ));
582                 if ( gp ) {
583                     // Deal with gp
584                     //...
585                 }
586                 // Destructor of guarded_ptr releases internal HP guard
587             }
588             \endcode
589
590             Note the compare functor specified for class \p Traits template parameter
591             should accept a parameter of type \p K that can be not the same as \p key_type.
592         */
593         template <typename K>
594         guarded_ptr get( K const& key ) const
595         {
596             return base_class::get( key );
597         }
598
599         /// Finds the \p key and return the item found
600         /**
601             The function is an analog of \p get( guarded_ptr& ptr, K const&)
602             but \p pred is used for comparing the keys.
603
604             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
605             in any order.
606             \p pred must imply the same element order as the comparator used for building the list.
607         */
608         template <typename K, typename Less>
609         guarded_ptr get_with( K const& key, Less pred ) const
610         {
611             CDS_UNUSED( pred );
612             return base_class::get_with( key, less_wrapper<Less>() );
613         }
614
615         /// Checks if the list is empty
616         /**
617             Emptiness is checked by item counting: if item count is zero then the set is empty.
618             Thus, if you need to use \p %empty() you should provide appropriate (non-empty) \p iterable_list::traits::item_counter
619             feature.
620         */
621         bool empty() const
622         {
623             return base_class::empty();
624         }
625
626         /// Returns list's item count
627         /**
628             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
629             this function always returns 0.
630         */
631         size_t size() const
632         {
633             return base_class::size();
634         }
635
636         /// Clears the list
637         void clear()
638         {
639             base_class::clear();
640         }
641
642         /// Returns const reference to internal statistics
643         stat const& statistics() const
644         {
645             return base_class::statistics();
646         }
647
648     protected:
649         //@cond
650         // Split-list support
651
652         template <typename K>
653         bool insert_at( head_type& refHead, K const& key )
654         {
655             return base_class::insert_at( refHead, value_type( key_type( key ), mapped_type() ));
656         }
657
658         template <typename K, typename V>
659         bool insert_at( head_type& refHead, const K& key, V const& val )
660         {
661             return base_class::insert_at( refHead, value_type( key_type( key ), val ));
662         }
663
664         template <typename K, typename Func>
665         bool insert_with_at( head_type& refHead, K const& key, Func f )
666         {
667             return base_class::insert_at( refHead, value_type( key_type( key ), mapped_type()), f );
668         }
669
670         template <typename K, typename... Args>
671         bool emplace_at( head_type& refHead, K&& key, Args&&... args )
672         {
673             return base_class::emplace_at( refHead, std::forward<K>(key), std::forward<Args>(args)... );
674         }
675
676         template <typename K, typename Func>
677         std::pair<bool, bool> update_at( head_type& refHead, const K& key, Func f, bool bAllowInsert )
678         {
679             return base_class::update_at( refHead, value_type( key_type( key ), mapped_type()), f, bAllowInsert );
680         }
681
682         template <typename K, typename Compare>
683         bool erase_at( head_type& refHead, K const& key, Compare cmp )
684         {
685             return base_class::erase_at( refHead, key, cmp );
686         }
687
688         template <typename K, typename Compare, typename Func>
689         bool erase_at( head_type& refHead, K const& key, Compare cmp, Func f )
690         {
691             return base_class::erase_at( refHead, key, cmp, f );
692         }
693         template <typename K, typename Compare>
694         bool extract_at( head_type& refHead, typename guarded_ptr::native_guard& guard, K const& key, Compare cmp )
695         {
696             return base_class::extract_at( refHead, guard, key, cmp );
697         }
698
699         template <typename K, typename Compare>
700         bool find_at( head_type& refHead, K const& key, Compare cmp )
701         {
702             return base_class::find_at( refHead, key, cmp );
703         }
704
705         template <typename K, typename Compare, typename Func>
706         bool find_at( head_type& refHead, K& key, Compare cmp, Func f )
707         {
708             return base_class::find_at( refHead, key, cmp, f );
709         }
710
711         template <typename K, typename Compare>
712         bool get_at( head_type& refHead, typename guarded_ptr::native_guard& guard, K const& key, Compare cmp )
713         {
714             return base_class::get_at( refHead, guard, key, cmp );
715         }
716
717         //@endcond
718     };
719
720 }}  // namespace cds::container
721
722 #endif  // #ifndef CDSLIB_CONTAINER_IMPL_ITERABLE_KVLIST_H