4295ef8f30312e27f91e7fa774425d2ab22c024e
[libcds.git] / cds / container / split_list_map.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_SPLIT_LIST_MAP_H
32 #define CDSLIB_CONTAINER_SPLIT_LIST_MAP_H
33
34 #include <cds/container/split_list_set.h>
35 #include <cds/details/binary_functor_wrapper.h>
36
37 namespace cds { namespace container {
38
39     /// Split-ordered list map
40     /** @ingroup cds_nonintrusive_map
41         \anchor cds_nonintrusive_SplitListMap_hp
42
43         Hash table implementation based on split-ordered list algorithm discovered by Ori Shalev and Nir Shavit, see
44         - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables"
45         - [2008] Nir Shavit "The Art of Multiprocessor Programming"
46
47         See intrusive::SplitListSet for a brief description of the split-list algorithm.
48
49         Template parameters:
50         - \p GC - Garbage collector used like \p cds::gc::HP or \p cds::gc::DHP
51         - \p Key - key type of an item stored in the map. It should be copy-constructible
52         - \p Value - value type stored in the map
53         - \p Traits - map traits, default is \p split_list::traits. Instead of declaring \p %split_list::traits -based
54             struct you may apply option-based notation with \p split_list::make_traits metafunction.
55
56         There are the specializations:
57         - for \ref cds_urcu_desc "RCU" - declared in <tt>cd/container/split_list_map_rcu.h</tt>,
58             see \ref cds_nonintrusive_SplitListMap_rcu "SplitListMap<RCU>".
59         - for \ref cds::gc::nogc declared in <tt>cds/container/split_list_map_nogc.h</tt>,
60             see \ref cds_nonintrusive_SplitListMap_nogc "SplitListMap<gc::nogc>".
61
62         \par Usage
63
64         You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list
65         is original data structure based on an ordered list. Suppose, you want construct split-list map based on \p gc::HP GC
66         and \p MichaelList as ordered list implementation. Your map should map \p int key to \p std::string value.
67         So, you beginning your code with the following:
68         \code
69         #include <cds/container/michael_list_hp.h>
70         #include <cds/container/split_list_map.h>
71
72         namespace cc = cds::container;
73         \endcode
74         The inclusion order is important: first, include file for ordered-list implementation (for this example, <tt>cds/container/michael_list_hp.h</tt>),
75         then the header for split-list map <tt>cds/container/split_list_map.h</tt>.
76
77         Now, you should declare traits for split-list map. The main parts of traits are a hash functor and a comparing functor for the ordered list.
78         We use <tt>std::hash<int></tt> as hash functor and <tt>std::less<int></tt> predicate as comparing functor.
79
80         The second attention: instead of using \p %MichaelList in \p %SplitListMap traits we use a tag \p cds::contaner::michael_list_tag for the Michael's list.
81         The split-list requires significant support from underlying ordered list class and it is not good idea to dive you
82         into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface.
83
84         \code
85         // SplitListMap traits
86         struct foo_set_traits: public cc::split_list::traits
87         {
88             typedef cc::michael_list_tag   ordered_list    ;   // what type of ordered list we want to use
89             typedef std::hash<int>         hash            ;   // hash functor for the key stored in split-list map
90
91             // Type traits for our MichaelList class
92             struct ordered_list_traits: public cc::michael_list::traits
93             {
94             typedef std::less<int> less   ;   // use our std::less predicate as comparator to order list nodes
95             };
96         };
97         \endcode
98
99         Now you are ready to declare our map class based on \p %SplitListMap:
100         \code
101         typedef cc::SplitListMap< cds::gc::DHP, int, std::string, foo_set_traits > int_string_map;
102         \endcode
103
104         You may use the modern option-based declaration instead of classic type-traits-based one:
105         \code
106         typedef cc::SplitListMap<
107             cs::gc::DHP             // GC used
108             ,int                    // key type
109             ,std::string            // value type
110             ,cc::split_list::make_traits<      // metafunction to build split-list traits
111                 cc::split_list::ordered_list<cc::michael_list_tag>     // tag for underlying ordered list implementation
112                 ,cc::opt::hash< std::hash<int> >        // hash functor
113                 ,cc::split_list::ordered_list_traits<    // ordered list traits desired
114                     cc::michael_list::make_traits<    // metafunction to build lazy list traits
115                         cc::opt::less< std::less<int> >         // less-based compare functor
116                     >::type
117                 >
118             >::type
119         >  int_string_map;
120         \endcode
121         In case of option-based declaration with \p split_list::make_traits metafunction the struct \p foo_set_traits is not required.
122
123         Now, the map of type \p int_string_map is ready to use in your program.
124
125         Note that in this example we show only mandatory \p traits parts, optional ones is the default and they are inherited
126         from \p container::split_list::traits. There are many other options for deep tuning of the split-list and
127         ordered-list containers.
128     */
129     template <
130         class GC,
131         typename Key,
132         typename Value,
133 #ifdef CDS_DOXYGEN_INVOKED
134         class Traits = split_list::traits
135 #else
136         class Traits
137 #endif
138     >
139     class SplitListMap:
140         protected container::SplitListSet<
141             GC,
142             std::pair<Key const, Value>,
143             split_list::details::wrap_map_traits<Key, Value, Traits>
144         >
145     {
146         //@cond
147         typedef container::SplitListSet<
148             GC,
149             std::pair<Key const, Value>,
150             split_list::details::wrap_map_traits<Key, Value, Traits>
151         >  base_class;
152         //@endcond
153
154     public:
155         typedef GC     gc;          ///< Garbage collector
156         typedef Key    key_type;    ///< key type
157         typedef Value  mapped_type; ///< type of value to be stored in the map
158         typedef Traits traits;      ///< Map traits
159
160         typedef std::pair<key_type const, mapped_type>  value_type  ;   ///< key-value pair type
161         typedef typename base_class::ordered_list       ordered_list;   ///< Underlying ordered list class
162         typedef typename base_class::key_comparator     key_comparator; ///< key compare functor
163
164         typedef typename base_class::hash           hash;         ///< Hash functor for \ref key_type
165         typedef typename base_class::item_counter   item_counter; ///< Item counter type
166         typedef typename base_class::stat           stat;         ///< Internal statistics
167
168         /// Count of hazard pointer required
169         static CDS_CONSTEXPR const size_t c_nHazardPtrCount = base_class::c_nHazardPtrCount;
170
171     protected:
172         //@cond
173         typedef typename base_class::maker::traits::key_accessor key_accessor;
174         typedef typename base_class::node_type node_type;
175         //@endcond
176
177     public:
178         /// Guarded pointer
179         typedef typename gc::template guarded_ptr< node_type, value_type, details::guarded_ptr_cast_set<node_type, value_type> > guarded_ptr;
180
181     public:
182     ///@name Forward iterators (only for debugging purpose)
183     //@{
184         /// Forward iterator
185         /**
186             The forward iterator for a split-list has the following features:
187             - it has no post-increment operator
188             - it depends on underlying ordered list iterator
189             - The iterator object cannot be moved across thread boundary because it contains GC's guard that is thread-private GC data.
190             - Iterator ensures thread-safety even if you delete the item that iterator points to. However, in case of concurrent
191               deleting operations it is no guarantee that you iterate all item in the split-list.
192               Moreover, a crash is possible when you try to iterate the next element that has been deleted by concurrent thread.
193
194               @warning Use this iterator on the concurrent container for debugging purpose only.
195
196               The iterator interface:
197               \code
198               class iterator {
199               public:
200                   // Default constructor
201                   iterator();
202
203                   // Copy construtor
204                   iterator( iterator const& src );
205
206                   // Dereference operator
207                   value_type * operator ->() const;
208
209                   // Dereference operator
210                   value_type& operator *() const;
211
212                   // Preincrement operator
213                   iterator& operator ++();
214
215                   // Assignment operator
216                   iterator& operator = (iterator const& src);
217
218                   // Equality operators
219                   bool operator ==(iterator const& i ) const;
220                   bool operator !=(iterator const& i ) const;
221               };
222               \endcode
223         */
224         typedef typename base_class::iterator iterator;
225
226         /// Const forward iterator
227         typedef typename base_class::const_iterator const_iterator;
228
229         /// Returns a forward iterator addressing the first element in a map
230         /**
231             For empty map \code begin() == end() \endcode
232         */
233         iterator begin()
234         {
235             return base_class::begin();
236         }
237
238         /// Returns an iterator that addresses the location succeeding the last element in a map
239         /**
240             Do not use the value returned by <tt>end</tt> function to access any item.
241             The returned value can be used only to control reaching the end of the map.
242             For empty map \code begin() == end() \endcode
243         */
244         iterator end()
245         {
246             return base_class::end();
247         }
248
249         /// Returns a forward const iterator addressing the first element in a map
250         const_iterator begin() const
251         {
252             return base_class::begin();
253         }
254
255         /// Returns a forward const iterator addressing the first element in a map
256         const_iterator cbegin() const
257         {
258             return base_class::cbegin();
259         }
260
261         /// Returns an const iterator that addresses the location succeeding the last element in a map
262         const_iterator end() const
263         {
264             return base_class::end();
265         }
266
267         /// Returns an const iterator that addresses the location succeeding the last element in a map
268         const_iterator cend() const
269         {
270             return base_class::cend();
271         }
272     //@}
273
274     public:
275         /// Initializes split-ordered map of default capacity
276         /**
277             The default capacity is defined in bucket table constructor.
278             See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table
279             which selects by \p intrusive::split_list::traits::dynamic_bucket_table.
280         */
281         SplitListMap()
282             : base_class()
283         {}
284
285         /// Initializes split-ordered map
286         SplitListMap(
287             size_t nItemCount           ///< estimated average item count
288             , size_t nLoadFactor = 1    ///< load factor - average item count per bucket. Small integer up to 10, default is 1.
289             )
290             : base_class( nItemCount, nLoadFactor )
291         {}
292
293     public:
294         /// Inserts new node with key and default value
295         /**
296             The function creates a node with \p key and default value, and then inserts the node created into the map.
297
298             Preconditions:
299             - The \ref key_type should be constructible from value of type \p K.
300                 In trivial case, \p K is equal to \ref key_type.
301             - The \ref mapped_type should be default-constructible.
302
303             Returns \p true if inserting successful, \p false otherwise.
304         */
305         template <typename K>
306         bool insert( K&& key )
307         {
308             return base_class::emplace( key_type( std::forward<K>( key )), mapped_type() );
309         }
310
311         /// Inserts new node
312         /**
313             The function creates a node with copy of \p val value
314             and then inserts the node created into the map.
315
316             Preconditions:
317             - The \ref key_type should be constructible from \p key of type \p K.
318             - The \ref mapped_type should be constructible from \p val of type \p V.
319
320             Returns \p true if \p val is inserted into the map, \p false otherwise.
321         */
322         template <typename K, typename V>
323         bool insert( K&& key, V&& val )
324         {
325             return base_class::emplace( key_type( std::forward<K>( key )), mapped_type( std::forward<V>( val )));
326         }
327
328         /// Inserts new node and initialize it by a functor
329         /**
330             This function inserts new node with key \p key and if inserting is successful then it calls
331             \p func functor with signature
332             \code
333                 struct functor {
334                     void operator()( value_type& item );
335                 };
336             \endcode
337
338             The argument \p item of user-defined functor \p func is the reference
339             to the map's item inserted:
340                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
341                 - <tt>item.second</tt> is a reference to item's value that may be changed.
342
343             It should be keep in mind that concurrent modifications of \p <tt>item.second</tt> may be possible.
344
345             The key_type should be constructible from value of type \p K.
346
347             The function allows to split creating of new item into two part:
348             - create item from \p key;
349             - insert new item into the map;
350             - if inserting is successful, initialize the value of item by calling \p func functor
351
352             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
353             it is preferable that the initialization should be completed only if inserting is successful.
354
355             @warning For \ref cds_nonintrusive_MichaelKVList_gc "MichaelKVList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
356             \ref cds_nonintrusive_LazyKVList_gc "LazyKVList" provides exclusive access to inserted item and does not require any node-level
357             synchronization.
358         */
359         template <typename K, typename Func>
360         bool insert_with( K&& key, Func func )
361         {
362             //TODO: pass arguments by reference (make_pair makes copy)
363             return base_class::insert( std::make_pair( key_type( std::forward<K>( key )), mapped_type()), func );
364         }
365
366         /// For key \p key inserts data of type \p mapped_type created from \p args
367         /**
368             \p key_type should be constructible from type \p K
369
370             Returns \p true if inserting successful, \p false otherwise.
371         */
372         template <typename K, typename... Args>
373         bool emplace( K&& key, Args&&... args )
374         {
375             return base_class::emplace( key_type( std::forward<K>(key)), mapped_type( std::forward<Args>(args)...));
376         }
377
378         /// Updates the node
379         /**
380             The operation performs inserting or changing data with lock-free manner.
381
382             If \p key is not found in the map, then \p key is inserted iff \p bAllowInsert is \p true.
383             Otherwise, the functor \p func is called with item found.
384
385             The functor \p func signature depends on ordered list:
386
387             <b>for \p MichaelKVList, \p LazyKVList</b>
388             \code
389                 struct my_functor {
390                     void operator()( bool bNew, value_type& item );
391                 };
392             \endcode
393             with arguments:
394             - \p bNew - \p true if the item has been inserted, \p false otherwise
395             - \p item - the item found or inserted
396
397             The functor may change any fields of the \p item.second that is \p mapped_type.
398
399             <b>for \p IterableKVList</b>
400             \code
401                 void func( value_type& val, value_type * old );
402             \endcode
403             where
404             - \p val - a new data constructed from \p key
405             - \p old - old value that will be retired. If new item has been inserted then \p old is \p nullptr.
406
407             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
408             \p second is true if new item has been added or \p false if the item with \p key
409             already is in the map.
410
411             @warning For \ref cds_nonintrusive_MichaelKVList_gc "MichaelKVList" and \ref cds_nonintrusive_IterableKVList_gc "IterableKVList"
412             as the ordered list see \ref cds_intrusive_item_creating "insert item troubleshooting".
413             \ref cds_nonintrusive_LazyKVList_gc "LazyKVList" provides exclusive access to inserted item and does not require any node-level
414             synchronization.
415         */
416         template <typename K, typename Func>
417 #ifdef CDS_DOXYGE_INVOKED
418         std::pair<bool, bool>
419 #else
420         typename std::enable_if<
421             std::is_same<K,K>::value && !is_iterable_list< ordered_list >::value,
422             std::pair<bool, bool>
423         >::type
424 #endif
425         update( K&& key, Func func, bool bAllowInsert = true )
426         {
427             typedef decltype( std::make_pair( key_type( std::forward<K>( key )), mapped_type() )) arg_pair_type;
428
429             return base_class::update( std::make_pair( key_type( key ), mapped_type()),
430                 [&func]( bool bNew, value_type& item, arg_pair_type const& /*val*/ ) {
431                     func( bNew, item );
432                 },
433                 bAllowInsert );
434         }
435         //@cond
436         template <typename K, typename Func>
437 #ifdef CDS_DOXYGE_INVOKED
438         std::pair<bool, bool>
439 #else
440         typename std::enable_if<
441             std::is_same<K, K>::value && is_iterable_list< ordered_list >::value,
442             std::pair<bool, bool>
443         >::type
444 #endif
445         update( K&& key, Func func, bool bAllowInsert = true )
446         {
447             return base_class::update( std::make_pair( key_type( std::forward<K>( key )), mapped_type()), func, bAllowInsert );
448         }
449         //@endcond
450         //@cond
451         template <typename K, typename Func>
452         CDS_DEPRECATED("ensure() is deprecated, use update()")
453         std::pair<bool, bool> ensure( K const& key, Func func )
454         {
455             return update( key, func, true );
456         }
457         //@endcond
458
459         /// Inserts or updates the node (only for \p IterableKVList)
460         /**
461             The operation performs inserting or changing data with lock-free manner.
462
463             If \p key is not found in the map, then \p key is inserted iff \p bAllowInsert is \p true.
464             Otherwise, the current element is changed to \p val, the old element will be retired later.
465
466             Returns std::pair<bool, bool> where \p first is \p true if operation is successful,
467             \p second is \p true if \p val has been added or \p false if the item with that key
468             already in the map.
469             */
470         template <typename Q, typename V>
471 #ifdef CDS_DOXYGEN_INVOKED
472         std::pair<bool, bool>
473 #else
474         typename std::enable_if<
475             std::is_same< Q, Q>::value && is_iterable_list< ordered_list >::value,
476             std::pair<bool, bool>
477         >::type
478 #endif
479         upsert( Q&& key, V&& val, bool bAllowInsert = true )
480         {
481             return base_class::upsert( std::make_pair( std::forward<Q>( key ), std::forward<V>( val )), bAllowInsert );
482         }
483
484
485         /// Deletes \p key from the map
486         /** \anchor cds_nonintrusive_SplitListMap_erase_val
487
488             Return \p true if \p key is found and deleted, \p false otherwise
489         */
490         template <typename K>
491         bool erase( K const& key )
492         {
493             return base_class::erase( key );
494         }
495
496         /// Deletes the item from the map using \p pred predicate for searching
497         /**
498             The function is an analog of \ref cds_nonintrusive_SplitListMap_erase_val "erase(K const&)"
499             but \p pred is used for key comparing.
500             \p Less functor has the interface like \p std::less.
501             \p Less must imply the same element order as the comparator used for building the map.
502         */
503         template <typename K, typename Less>
504         bool erase_with( K const& key, Less pred )
505         {
506             CDS_UNUSED( pred );
507             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
508         }
509
510         /// Deletes \p key from the map
511         /** \anchor cds_nonintrusive_SplitListMap_erase_func
512
513             The function searches an item with key \p key, calls \p f functor
514             and deletes the item. If \p key is not found, the functor is not called.
515
516             The functor \p Func interface is:
517             \code
518             struct extractor {
519                 void operator()(value_type& item) { ... }
520             };
521             \endcode
522
523             Return \p true if key is found and deleted, \p false otherwise
524         */
525         template <typename K, typename Func>
526         bool erase( K const& key, Func f )
527         {
528             return base_class::erase( key, f );
529         }
530
531         /// Deletes the item from the map using \p pred predicate for searching
532         /**
533             The function is an analog of \ref cds_nonintrusive_SplitListMap_erase_func "erase(K const&, Func)"
534             but \p pred is used for key comparing.
535             \p Less functor has the interface like \p std::less.
536             \p Less must imply the same element order as the comparator used for building the map.
537         */
538         template <typename K, typename Less, typename Func>
539         bool erase_with( K const& key, Less pred, Func f )
540         {
541             CDS_UNUSED( pred );
542             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>(), f );
543         }
544
545         /// Extracts the item with specified \p key
546         /** \anchor cds_nonintrusive_SplitListMap_hp_extract
547             The function searches an item with key equal to \p key,
548             unlinks it from the map, and returns it as \p guarded_ptr.
549             If \p key is not found the function returns an empty guarded pointer.
550
551             Note the compare functor should accept a parameter of type \p K that may be not the same as \p value_type.
552
553             The extracted item is freed automatically when returned \p guarded_ptr object will be destroyed or released.
554             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
555
556             Usage:
557             \code
558             typedef cds::container::SplitListMap< your_template_args > splitlist_map;
559             splitlist_map theMap;
560             // ...
561             {
562                 splitlist_map::guarded_ptr gp(theMap.extract( 5 ));
563                 if ( gp ) {
564                     // Deal with gp
565                     // ...
566                 }
567                 // Destructor of gp releases internal HP guard
568             }
569             \endcode
570         */
571         template <typename K>
572         guarded_ptr extract( K const& key )
573         {
574             return base_class::extract_( key );
575         }
576
577         /// Extracts the item using compare functor \p pred
578         /**
579             The function is an analog of \ref cds_nonintrusive_SplitListMap_hp_extract "extract(K const&)"
580             but \p pred predicate is used for key comparing.
581
582             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
583             in any order.
584             \p pred must imply the same element order as the comparator used for building the map.
585         */
586         template <typename K, typename Less>
587         guarded_ptr extract_with( K const& key, Less pred )
588         {
589             CDS_UNUSED( pred );
590             return base_class::extract_with_( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
591         }
592
593         /// Finds the key \p key
594         /** \anchor cds_nonintrusive_SplitListMap_find_cfunc
595
596             The function searches the item with key equal to \p key and calls the functor \p f for item found.
597             The interface of \p Func functor is:
598             \code
599             struct functor {
600                 void operator()( value_type& item );
601             };
602             \endcode
603             where \p item is the item found.
604
605             The functor may change \p item.second. Note that the functor is only guarantee
606             that \p item cannot be disposed during functor is executing.
607             The functor does not serialize simultaneous access to the map's \p item. If such access is
608             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
609
610             The function returns \p true if \p key is found, \p false otherwise.
611         */
612         template <typename K, typename Func>
613         bool find( K const& key, Func f )
614         {
615             return base_class::find( key, [&f](value_type& pair, K const&){ f( pair ); } );
616         }
617
618         /// Finds \p key and returns iterator pointed to the item found (only for \p IterableList)
619         /**
620             If \p key is not found the function returns \p end().
621
622             @note This function is supported only for map based on \p IterableList
623         */
624         template <typename K>
625 #ifdef CDS_DOXYGEN_INVOKED
626         iterator
627 #else
628         typename std::enable_if< std::is_same<K,K>::value && is_iterable_list<ordered_list>::value, iterator >::type
629 #endif
630         find( K const& key )
631         {
632             return base_class::find( key );
633         }
634
635         /// Finds the key \p val using \p pred predicate for searching
636         /**
637             The function is an analog of \ref cds_nonintrusive_SplitListMap_find_cfunc "find(K const&, Func)"
638             but \p pred is used for key comparing.
639             \p Less functor has the interface like \p std::less.
640             \p Less must imply the same element order as the comparator used for building the map.
641         */
642         template <typename K, typename Less, typename Func>
643         bool find_with( K const& key, Less pred, Func f )
644         {
645             CDS_UNUSED( pred );
646             return base_class::find_with( key,
647                 cds::details::predicate_wrapper<value_type, Less, key_accessor>(),
648                 [&f](value_type& pair, K const&){ f( pair ); } );
649         }
650
651         /// Finds \p key using \p pred predicate and returns iterator pointed to the item found (only for \p IterableList)
652         /**
653             The function is an analog of \p find(K&) but \p pred is used for key comparing.
654             \p Less functor has interface like \p std::less.
655             \p pred must imply the same element order as the comparator used for building the map.
656
657             If \p key is not found the function returns \p end().
658
659             @note This function is supported only for map based on \p IterableList
660         */
661         template <typename K, typename Less>
662 #ifdef CDS_DOXYGEN_INVOKED
663         iterator
664 #else
665         typename std::enable_if< std::is_same<K, K>::value && is_iterable_list< ordered_list >::value, iterator >::type
666 #endif
667         find_with( K const& key, Less pred )
668         {
669             CDS_UNUSED( pred );
670             return base_class::find_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
671         }
672
673         /// Checks whether the map contains \p key
674         /**
675             The function searches the item with key equal to \p key
676             and returns \p true if it is found, and \p false otherwise.
677
678             Note the hash functor specified for class \p Traits template parameter
679             should accept a parameter of type \p Q that can be not the same as \p value_type.
680             Otherwise, you may use \p contains( Q const&, Less pred ) functions with explicit predicate for key comparing.
681         */
682         template <typename K>
683         bool contains( K const& key )
684         {
685             return base_class::contains( key );
686         }
687
688         /// Checks whether the map contains \p key using \p pred predicate for searching
689         /**
690             The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
691             \p Less functor has the interface like \p std::less.
692             \p Less must imply the same element order as the comparator used for building the map.
693         */
694         template <typename K, typename Less>
695         bool contains( K const& key, Less pred )
696         {
697             CDS_UNUSED( pred );
698             return base_class::contains( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
699         }
700
701         /// Finds \p key and return the item found
702         /** \anchor cds_nonintrusive_SplitListMap_hp_get
703             The function searches the item with key equal to \p key
704             and returns the item found as a guarded pointer.
705             If \p key is not found the function returns an empty guarded pointer.
706
707             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
708
709             Usage:
710             \code
711             typedef cds::container::SplitListMap< your_template_params >  splitlist_map;
712             splitlist_map theMap;
713             // ...
714             {
715                 splitlist_map::guarded_ptr gp(theMap.get( 5 ));
716                 if ( gp ) {
717                     // Deal with gp
718                     //...
719                 }
720                 // Destructor of guarded_ptr releases internal HP guard
721             }
722             \endcode
723
724             Note the compare functor specified for split-list map
725             should accept a parameter of type \p K that can be not the same as \p value_type.
726         */
727         template <typename K>
728         guarded_ptr get( K const& key )
729         {
730             return base_class::get_( key );
731         }
732
733         /// Finds \p key and return the item found
734         /**
735             The function is an analog of \ref cds_nonintrusive_SplitListMap_hp_get "get( K const&)"
736             but \p pred is used for comparing the keys.
737
738             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
739             in any order.
740             \p pred must imply the same element order as the comparator used for building the map.
741         */
742         template <typename K, typename Less>
743         guarded_ptr get_with( K const& key, Less pred )
744         {
745             CDS_UNUSED( pred );
746             return base_class::get_with_( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
747         }
748
749         /// Clears the map (not atomic)
750         void clear()
751         {
752             base_class::clear();
753         }
754
755         /// Checks if the map is empty
756         /**
757             Emptiness is checked by item counting: if item count is zero then the map is empty.
758             Thus, the correct item counting is an important part of the map implementation.
759         */
760         bool empty() const
761         {
762             return base_class::empty();
763         }
764
765         /// Returns item count in the map
766         size_t size() const
767         {
768             return base_class::size();
769         }
770
771         /// Returns internal statistics
772         stat const& statistics() const
773         {
774             return base_class::statistics();
775         }
776
777         /// Returns internal statistics for \p ordered_list
778         typename ordered_list::stat const& list_statistics() const
779         {
780             return base_class::list_statistics();
781         }
782     };
783
784 }} // namespace cds::container
785
786 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_MAP_H