Fixed gcc incompatibility
[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 #ifdef CDS_DOXYGEN_INVOKED
253         bool
254 #else
255         typename std::enable_if<
256             std::is_same<K, K>::value && std::is_default_constructible< mapped_type >::value,
257             bool
258         >::type
259 #endif
260         insert( K const& key )
261         {
262             return base_class::emplace( key, mapped_type());
263         }
264
265         /// Inserts new node with a key and a value
266         /**
267             The function creates a node with \p key and value \p val, and then inserts the node created into the list.
268
269             Preconditions:
270             - The \p key_type should be constructible from \p key of type \p K.
271             - The \p mapped_type should be constructible from \p val of type \p V.
272
273             Returns \p true if inserting successful, \p false otherwise.
274         */
275         template <typename K, typename V>
276         bool insert( K const& key, V const& val )
277         {
278             return base_class::emplace( key, val );
279         }
280
281         /// Inserts new node and initialize it by a functor
282         /**
283             This function inserts new node with key \p key and if inserting is successful then it calls
284             \p func functor with signature
285             \code
286                 struct functor {
287                     void operator()( value_type& item );
288                 };
289             \endcode
290
291             The argument \p item of user-defined functor \p func is the reference
292             to the item inserted. <tt>item.second</tt> is a reference to item's value that may be changed.
293             User-defined functor \p func should guarantee that during changing item's value no any other changes
294             could be made on this list's item by concurrent threads.
295             The user-defined functor is called only if inserting is successful.
296
297             The \p key_type should be constructible from value of type \p K.
298
299             The function allows to split creating of new item into two part:
300             - create a new item from \p key;
301             - insert the new item into the list;
302             - if inserting is successful, initialize the value of item by calling \p func functor
303
304             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
305             it is preferable that the initialization should be completed only if inserting is successful.
306
307             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
308
309             @note The function is supported only if \ref mapped_type is default constructible
310         */
311         template <typename K, typename Func>
312 #ifdef CDS_DOXYGEN_INVOKED
313         bool
314 #else
315         typename std::enable_if<
316             std::is_same<K, K>::value && std::is_default_constructible< mapped_type >::value,
317             bool
318         >::type
319 #endif
320         insert_with( K const& key, Func func )
321         {
322             return base_class::insert( value_type( key, mapped_type()), func );
323         }
324
325         /// Updates data by \p key
326         /**
327             The operation performs inserting or replacing the element with lock-free manner.
328
329             If the \p key not found in the list, then the new item created from \p key
330             will be inserted iff \p bAllowInsert is \p true.
331             (note that in this case the \ref key_type should be constructible from type \p K).
332             Otherwise, if \p key is found, the functor \p func is called with item found.
333
334             The functor \p func is called after inserting or replacing, it signature is:
335             \code
336                 void func( value_type& val, value_type* old );
337             \endcode
338             where
339             - \p val - a new data constructed from \p key
340             - \p old - old value that will be retired. If new item has been inserted then \p old is \p nullptr.
341
342             The functor may change non-key fields of \p val; however, \p func must guarantee
343             that during changing no any other modifications could be made on this item by concurrent threads.
344
345             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
346             \p second is true if new item has been added or \p false if the item with such \p key
347             already exists.
348
349             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
350
351             @note The function is supported only if \ref mapped_type is default constructible
352         */
353         template <typename K, typename Func>
354 #ifdef CDS_DOXYGEN_INVOKED
355         std::pair<bool, bool>
356 #else
357         typename std::enable_if<
358             std::is_same<K, K>::value && std::is_default_constructible< mapped_type >::value,
359             std::pair<bool, bool>
360         >::type
361 #endif
362         update( K const& key, Func f, bool bAllowInsert = true )
363         {
364             return base_class::update( value_type( key, mapped_type()), f, bAllowInsert );
365         }
366
367         /// Insert or update
368         /**
369             The operation performs inserting or updating data with lock-free manner.
370
371             If the item \p key is not found in the list, then \p key is inserted
372             iff \p bInsert is \p true.
373             Otherwise, the current element is changed to <tt> value_type( key, val )</tt>, 
374             the old element will be retired later.
375
376             Returns std::pair<bool, bool> where \p first is \p true if operation is successful,
377             \p second is \p true if \p key has been added or \p false if the item with that key
378             already in the list.
379         */
380         template <typename Q, typename V >
381         std::pair<bool, bool> upsert( Q&& key, V&& val, bool bInsert = true )
382         {
383             return base_class::upsert( value_type( std::forward<Q>( key ), std::forward<V>( val )), bInsert );
384         }
385
386         /// Inserts a new node using move semantics
387         /**
388             \p key_type field of new item is constructed from \p key argument,
389             \p mapped_type field is done from \p args.
390
391             Returns \p true if inserting successful, \p false otherwise.
392         */
393         template <typename K, typename... Args>
394         bool emplace( K&& key, Args&&... args )
395         {
396             return base_class::emplace( std::forward<K>( key ), std::forward<Args>( args )... );
397         }
398
399         /// Deletes \p key from the list
400         /**
401
402             Returns \p true if \p key is found and has been deleted, \p false otherwise
403         */
404         template <typename K>
405         bool erase( K const& key )
406         {
407             return base_class::erase( key );
408         }
409
410         /// Deletes the item from the list using \p pred predicate for searching
411         /**
412             The function is an analog of \p erase(K const&) but \p pred is used for key comparing.
413             \p Less functor has the interface like \p std::less.
414             \p pred must imply the same element order as the comparator used for building the list.
415         */
416         template <typename K, typename Less>
417         bool erase_with( K const& key, Less pred )
418         {
419             CDS_UNUSED( pred );
420             return base_class::erase_with( key, less_wrapper<Less>() );
421         }
422
423         /// Deletes \p key from the list
424         /**
425             The function searches an item with key \p key, calls \p f functor
426             and deletes the item. If \p key is not found, the functor is not called.
427
428             The functor \p Func interface:
429             \code
430             struct extractor {
431                 void operator()(value_type& val) { ... }
432             };
433             \endcode
434
435             Return \p true if key is found and deleted, \p false otherwise
436         */
437         template <typename K, typename Func>
438         bool erase( K const& key, Func f )
439         {
440             return base_class::erase( key, f );
441         }
442
443         /// Deletes the item from the list using \p pred predicate for searching
444         /**
445             The function is an analog of \p erase(K const&, Func) but \p pred is used for key comparing.
446             \p Less functor has the interface like \p std::less.
447             \p pred must imply the same element order as the comparator used for building the list.
448         */
449         template <typename K, typename Less, typename Func>
450         bool erase_with( K const& key, Less pred, Func f )
451         {
452             CDS_UNUSED( pred );
453             return base_class::erase_with( key, less_wrapper<Less>(), f );
454         }
455
456         /// Extracts the item from the list with specified \p key
457         /**
458             The function searches an item with key equal to \p key,
459             unlinks it from the list, and returns it as \p guarded_ptr.
460             If \p key is not found the function returns an empty guarded pointer.
461
462             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
463
464             The \p disposer specified in \p Traits class template parameter is called automatically
465             by garbage collector \p GC specified in class' template parameters when returned \p guarded_ptr object
466             will be destroyed or released.
467             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
468
469             Usage:
470             \code
471             typedef cds::container::IterableKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
472             ord_list theList;
473             // ...
474             {
475                 ord_list::guarded_ptr gp(theList.extract( 5 ));
476                 if ( gp ) {
477                     // Deal with gp
478                     // ...
479                 }
480                 // Destructor of gp releases internal HP guard
481             }
482             \endcode
483         */
484         template <typename K>
485         guarded_ptr extract( K const& key )
486         {
487             return base_class::extract( key );
488         }
489
490         /// Extracts the item from the list with comparing functor \p pred
491         /**
492             The function is an analog of \p extract(K const&) but \p pred predicate is used for key comparing.
493
494             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
495             in any order.
496             \p pred must imply the same element order as the comparator used for building the list.
497         */
498         template <typename K, typename Less>
499         guarded_ptr extract_with( K const& key, Less pred )
500         {
501             CDS_UNUSED( pred );
502             return base_class::extract_with( key, less_wrapper<Less>() );
503         }
504
505         /// Checks whether the list contains \p key
506         /**
507             The function searches the item with key equal to \p key
508             and returns \p true if it is found, and \p false otherwise.
509         */
510         template <typename Q>
511         bool contains( Q const& key ) const
512         {
513             return base_class::contains( key );
514         }
515
516         /// Checks whether the map contains \p key using \p pred predicate for searching
517         /**
518             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
519             \p Less functor has the interface like \p std::less.
520             \p Less must imply the same element order as the comparator used for building the list.
521         */
522         template <typename Q, typename Less>
523         bool contains( Q const& key, Less pred ) const
524         {
525             CDS_UNUSED( pred );
526             return base_class::contains( key, less_wrapper<Less>() );
527         }
528
529         /// Finds the key \p key and performs an action with it
530         /**
531             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
532             The interface of \p Func functor is:
533             \code
534             struct functor {
535                 void operator()( value_type& item );
536             };
537             \endcode
538             where \p item is the item found.
539
540             The functor may change <tt>item.second</tt> that is reference to value of node.
541             Note that the function is only guarantee that \p item cannot be deleted during functor is executing.
542             The function does not serialize simultaneous access to the list \p item. If such access is
543             possible you must provide your own synchronization schema to exclude unsafe item modifications.
544
545             The function returns \p true if \p key is found, \p false otherwise.
546         */
547         template <typename Q, typename Func>
548         bool find( Q const& key, Func f ) const
549         {
550             return base_class::find( key, [&f]( value_type& v, Q const& ) { f( v ); } );
551         }
552
553         /// Finds \p key in the list and returns iterator pointed to the item found
554         /**
555             If \p key is not found the function returns \p end().
556         */
557         template <typename Q>
558         iterator find( Q const& key ) const
559         {
560             return base_class::find( key );
561         }
562
563         /// Finds the key \p val using \p pred predicate for searching
564         /**
565             The function is an analog of \p find(Q&, Func) but \p pred is used for key comparing.
566             \p Less functor has the interface like \p std::less.
567             \p pred must imply the same element order as the comparator used for building the list.
568         */
569         template <typename Q, typename Less, typename Func>
570         bool find_with( Q const& key, Less pred, Func f ) const
571         {
572             CDS_UNUSED( pred );
573             return base_class::find_with( key, less_wrapper<Less>(), [&f]( value_type& v, Q const& ) { f( v ); } );
574         }
575
576         /// Finds \p key in the list using \p pred predicate for searching and returns iterator pointed to the item found
577         /**
578             The function is an analog of \p find(Q&) 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             If \p key is not found the function returns \p end().
583         */
584         template <typename Q, typename Less>
585         iterator find_with( Q& key, Less pred ) const
586         {
587             CDS_UNUSED( pred );
588             return base_class::find_with( key, less_wrapper<Less>());
589         }
590
591         /// Finds the \p key and return the item found
592         /**
593             The function searches the item with key equal to \p key
594             and returns it as \p guarded_ptr.
595             If \p key is not found the function returns an empty guarded pointer.
596
597             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
598
599             Usage:
600             \code
601             typedef cds::container::IterableKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
602             ord_list theList;
603             // ...
604             {
605                 ord_list::guarded_ptr gp(theList.get( 5 ));
606                 if ( gp ) {
607                     // Deal with gp
608                     //...
609                 }
610                 // Destructor of guarded_ptr releases internal HP guard
611             }
612             \endcode
613
614             Note the compare functor specified for class \p Traits template parameter
615             should accept a parameter of type \p K that can be not the same as \p key_type.
616         */
617         template <typename K>
618         guarded_ptr get( K const& key ) const
619         {
620             return base_class::get( key );
621         }
622
623         /// Finds the \p key and return the item found
624         /**
625             The function is an analog of \p get( guarded_ptr& ptr, K const&)
626             but \p pred is used for comparing the keys.
627
628             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
629             in any order.
630             \p pred must imply the same element order as the comparator used for building the list.
631         */
632         template <typename K, typename Less>
633         guarded_ptr get_with( K const& key, Less pred ) const
634         {
635             CDS_UNUSED( pred );
636             return base_class::get_with( key, less_wrapper<Less>() );
637         }
638
639         /// Checks if the list is empty
640         /**
641             Emptiness is checked by item counting: if item count is zero then the set is empty.
642             Thus, if you need to use \p %empty() you should provide appropriate (non-empty) \p iterable_list::traits::item_counter
643             feature.
644         */
645         bool empty() const
646         {
647             return base_class::empty();
648         }
649
650         /// Returns list's item count
651         /**
652             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
653             this function always returns 0.
654         */
655         size_t size() const
656         {
657             return base_class::size();
658         }
659
660         /// Clears the list
661         void clear()
662         {
663             base_class::clear();
664         }
665
666         /// Returns const reference to internal statistics
667         stat const& statistics() const
668         {
669             return base_class::statistics();
670         }
671
672     protected:
673         //@cond
674         // Split-list support
675
676         template <typename K>
677         bool insert_at( head_type& refHead, const K& key )
678         {
679             return base_class::insert_at( refHead, value_type( key, mapped_type() ));
680         }
681
682         template <typename K, typename V>
683         bool insert_at( head_type& refHead, const K& key, const V& val )
684         {
685             return base_class::insert_at( refHead, value_type( key, val ));
686         }
687
688         template <typename K, typename Func>
689         bool insert_with_at( head_type& refHead, const K& key, Func f )
690         {
691             return base_class::insert_at( refHead, value_type( key, mapped_type()), f );
692         }
693
694         template <typename K, typename... Args>
695         bool emplace_at( head_type& refHead, K&& key, Args&&... args )
696         {
697             return base_class::emplace_at( refHead, std::forward<K>(key), std::forward<Args>(args)... );
698         }
699
700         template <typename K, typename Func>
701         std::pair<bool, bool> update_at( head_type& refHead, const K& key, Func f, bool bAllowInsert )
702         {
703             return base_class::update_at( refHead, value_type( key, mapped_type()), f, bAllowInsert );
704         }
705
706         template <typename K, typename Compare>
707         bool erase_at( head_type& refHead, K const& key, Compare cmp )
708         {
709             return base_class::erase_at( refHead, key, cmp );
710         }
711
712         template <typename K, typename Compare, typename Func>
713         bool erase_at( head_type& refHead, K const& key, Compare cmp, Func f )
714         {
715             return base_class::erase_at( refHead, key, cmp, f );
716         }
717         template <typename K, typename Compare>
718         bool extract_at( head_type& refHead, typename guarded_ptr::native_guard& guard, K const& key, Compare cmp )
719         {
720             return base_class::extract_at( refHead, guard, key, cmp );
721         }
722
723         template <typename K, typename Compare>
724         bool find_at( head_type& refHead, K const& key, Compare cmp )
725         {
726             return base_class::find_at( refHead, key, cmp );
727         }
728
729         template <typename K, typename Compare, typename Func>
730         bool find_at( head_type& refHead, K& key, Compare cmp, Func f )
731         {
732             return base_class::find_at( refHead, key, cmp, f );
733         }
734
735         template <typename K, typename Compare>
736         bool get_at( head_type& refHead, typename guarded_ptr::native_guard& guard, K const& key, Compare cmp )
737         {
738             return base_class::get_at( refHead, guard, key, cmp );
739         }
740
741         //@endcond
742     };
743
744 }}  // namespace cds::container
745
746 #endif  // #ifndef CDSLIB_CONTAINER_IMPL_ITERABLE_KVLIST_H