Uses different pass count for different parallel queue test cases
[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-2017
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( key_type( std::forward<Q>( key )), mapped_type( 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         /// Deletes the item pointed by iterator \p iter (only for \p IterableList based map)
546         /**
547             Returns \p true if the operation is successful, \p false otherwise.
548             The function can return \p false if the node the iterator points to has already been deleted
549             by other thread.
550
551             The function does not invalidate the iterator, it remains valid and can be used for further traversing.
552
553             @note \p %erase_at() is supported only for \p %SplitListMap based on \p IterableList.
554         */
555 #ifdef CDS_DOXYGEN_INVOKED
556         bool erase_at( iterator const& iter )
557 #else
558         template <typename Iterator>
559         typename std::enable_if< std::is_same<Iterator, iterator>::value && is_iterable_list< ordered_list >::value, bool >::type
560         erase_at( Iterator const& iter )
561 #endif
562         {
563             return base_class::erase_at( iter );
564         }
565
566         /// Extracts the item with specified \p key
567         /** \anchor cds_nonintrusive_SplitListMap_hp_extract
568             The function searches an item with key equal to \p key,
569             unlinks it from the map, and returns it as \p guarded_ptr.
570             If \p key is not found the function returns an empty guarded pointer.
571
572             Note the compare functor should accept a parameter of type \p K that may be not the same as \p value_type.
573
574             The extracted item is freed automatically when returned \p guarded_ptr object will be destroyed or released.
575             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
576
577             Usage:
578             \code
579             typedef cds::container::SplitListMap< your_template_args > splitlist_map;
580             splitlist_map theMap;
581             // ...
582             {
583                 splitlist_map::guarded_ptr gp(theMap.extract( 5 ));
584                 if ( gp ) {
585                     // Deal with gp
586                     // ...
587                 }
588                 // Destructor of gp releases internal HP guard
589             }
590             \endcode
591         */
592         template <typename K>
593         guarded_ptr extract( K const& key )
594         {
595             return base_class::extract_( key );
596         }
597
598         /// Extracts the item using compare functor \p pred
599         /**
600             The function is an analog of \ref cds_nonintrusive_SplitListMap_hp_extract "extract(K const&)"
601             but \p pred predicate is used for key comparing.
602
603             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
604             in any order.
605             \p pred must imply the same element order as the comparator used for building the map.
606         */
607         template <typename K, typename Less>
608         guarded_ptr extract_with( K const& key, Less pred )
609         {
610             CDS_UNUSED( pred );
611             return base_class::extract_with_( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
612         }
613
614         /// Finds the key \p key
615         /** \anchor cds_nonintrusive_SplitListMap_find_cfunc
616
617             The function searches the item with key equal to \p key and calls the functor \p f for item found.
618             The interface of \p Func functor is:
619             \code
620             struct functor {
621                 void operator()( value_type& item );
622             };
623             \endcode
624             where \p item is the item found.
625
626             The functor may change \p item.second. Note that the functor is only guarantee
627             that \p item cannot be disposed during functor is executing.
628             The functor does not serialize simultaneous access to the map's \p item. If such access is
629             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
630
631             The function returns \p true if \p key is found, \p false otherwise.
632         */
633         template <typename K, typename Func>
634         bool find( K const& key, Func f )
635         {
636             return base_class::find( key, [&f](value_type& pair, K const&){ f( pair ); } );
637         }
638
639         /// Finds \p key and returns iterator pointed to the item found (only for \p IterableList)
640         /**
641             If \p key is not found the function returns \p end().
642
643             @note This function is supported only for map based on \p IterableList
644         */
645         template <typename K>
646 #ifdef CDS_DOXYGEN_INVOKED
647         iterator
648 #else
649         typename std::enable_if< std::is_same<K,K>::value && is_iterable_list<ordered_list>::value, iterator >::type
650 #endif
651         find( K const& key )
652         {
653             return base_class::find( key );
654         }
655
656         /// Finds the key \p val using \p pred predicate for searching
657         /**
658             The function is an analog of \ref cds_nonintrusive_SplitListMap_find_cfunc "find(K const&, Func)"
659             but \p pred is used for key comparing.
660             \p Less functor has the interface like \p std::less.
661             \p Less must imply the same element order as the comparator used for building the map.
662         */
663         template <typename K, typename Less, typename Func>
664         bool find_with( K const& key, Less pred, Func f )
665         {
666             CDS_UNUSED( pred );
667             return base_class::find_with( key,
668                 cds::details::predicate_wrapper<value_type, Less, key_accessor>(),
669                 [&f](value_type& pair, K const&){ f( pair ); } );
670         }
671
672         /// Finds \p key using \p pred predicate and returns iterator pointed to the item found (only for \p IterableList)
673         /**
674             The function is an analog of \p find(K&) but \p pred is used for key comparing.
675             \p Less functor has interface like \p std::less.
676             \p pred must imply the same element order as the comparator used for building the map.
677
678             If \p key is not found the function returns \p end().
679
680             @note This function is supported only for map based on \p IterableList
681         */
682         template <typename K, typename Less>
683 #ifdef CDS_DOXYGEN_INVOKED
684         iterator
685 #else
686         typename std::enable_if< std::is_same<K, K>::value && is_iterable_list< ordered_list >::value, iterator >::type
687 #endif
688         find_with( K const& key, Less pred )
689         {
690             CDS_UNUSED( pred );
691             return base_class::find_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
692         }
693
694         /// Checks whether the map contains \p key
695         /**
696             The function searches the item with key equal to \p key
697             and returns \p true if it is found, and \p false otherwise.
698
699             Note the hash functor specified for class \p Traits template parameter
700             should accept a parameter of type \p Q that can be not the same as \p value_type.
701             Otherwise, you may use \p contains( Q const&, Less pred ) functions with explicit predicate for key comparing.
702         */
703         template <typename K>
704         bool contains( K const& key )
705         {
706             return base_class::contains( key );
707         }
708
709         /// Checks whether the map contains \p key using \p pred predicate for searching
710         /**
711             The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
712             \p Less functor has the interface like \p std::less.
713             \p Less must imply the same element order as the comparator used for building the map.
714         */
715         template <typename K, typename Less>
716         bool contains( K const& key, Less pred )
717         {
718             CDS_UNUSED( pred );
719             return base_class::contains( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
720         }
721
722         /// Finds \p key and return the item found
723         /** \anchor cds_nonintrusive_SplitListMap_hp_get
724             The function searches the item with key equal to \p key
725             and returns the item found as a guarded pointer.
726             If \p key is not found the function returns an empty guarded pointer.
727
728             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
729
730             Usage:
731             \code
732             typedef cds::container::SplitListMap< your_template_params >  splitlist_map;
733             splitlist_map theMap;
734             // ...
735             {
736                 splitlist_map::guarded_ptr gp(theMap.get( 5 ));
737                 if ( gp ) {
738                     // Deal with gp
739                     //...
740                 }
741                 // Destructor of guarded_ptr releases internal HP guard
742             }
743             \endcode
744
745             Note the compare functor specified for split-list map
746             should accept a parameter of type \p K that can be not the same as \p value_type.
747         */
748         template <typename K>
749         guarded_ptr get( K const& key )
750         {
751             return base_class::get_( key );
752         }
753
754         /// Finds \p key and return the item found
755         /**
756             The function is an analog of \ref cds_nonintrusive_SplitListMap_hp_get "get( K const&)"
757             but \p pred is used for comparing the keys.
758
759             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
760             in any order.
761             \p pred must imply the same element order as the comparator used for building the map.
762         */
763         template <typename K, typename Less>
764         guarded_ptr get_with( K const& key, Less pred )
765         {
766             CDS_UNUSED( pred );
767             return base_class::get_with_( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
768         }
769
770         /// Clears the map (not atomic)
771         void clear()
772         {
773             base_class::clear();
774         }
775
776         /// Checks if the map is empty
777         /**
778             Emptiness is checked by item counting: if item count is zero then the map is empty.
779             Thus, the correct item counting is an important part of the map implementation.
780         */
781         bool empty() const
782         {
783             return base_class::empty();
784         }
785
786         /// Returns item count in the map
787         size_t size() const
788         {
789             return base_class::size();
790         }
791
792         /// Returns internal statistics
793         stat const& statistics() const
794         {
795             return base_class::statistics();
796         }
797
798         /// Returns internal statistics for \p ordered_list
799         typename ordered_list::stat const& list_statistics() const
800         {
801             return base_class::list_statistics();
802         }
803     };
804
805 }} // namespace cds::container
806
807 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_MAP_H