Merge branch 'integration' into dev
[libcds.git] / cds / container / skip_list_map_rcu.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_CONTAINER_SKIP_LIST_MAP_RCU_H
4 #define CDSLIB_CONTAINER_SKIP_LIST_MAP_RCU_H
5
6 #include <cds/container/details/skip_list_base.h>
7 #include <cds/intrusive/skip_list_rcu.h>
8 #include <cds/container/details/make_skip_list_map.h>
9
10 namespace cds { namespace container {
11
12     /// Lock-free skip-list map (template specialization for \ref cds_urcu_desc "RCU")
13     /** @ingroup cds_nonintrusive_map
14         \anchor cds_nonintrusive_SkipListMap_rcu
15
16         The implementation of well-known probabilistic data structure called skip-list
17         invented by W.Pugh in his papers:
18             - [1989] W.Pugh Skip Lists: A Probabilistic Alternative to Balanced Trees
19             - [1990] W.Pugh A Skip List Cookbook
20
21         A skip-list is a probabilistic data structure that provides expected logarithmic
22         time search without the need of rebalance. The skip-list is a collection of sorted
23         linked list. Nodes are ordered by key. Each node is linked into a subset of the lists.
24         Each list has a level, ranging from 0 to 32. The bottom-level list contains
25         all the nodes, and each higher-level list is a sublist of the lower-level lists.
26         Each node is created with a random top level (with a random height), and belongs
27         to all lists up to that level. The probability that a node has the height 1 is 1/2.
28         The probability that a node has the height N is 1/2 ** N (more precisely,
29         the distribution depends on an random generator provided, but our generators
30         have this property).
31
32         The lock-free variant of skip-list is implemented according to book
33             - [2008] M.Herlihy, N.Shavit "The Art of Multiprocessor Programming",
34                 chapter 14.4 "A Lock-Free Concurrent Skiplist"
35
36         Template arguments:
37         - \p RCU - one of \ref cds_urcu_gc "RCU type".
38         - \p K - type of a key to be stored in the list.
39         - \p T - type of a value to be stored in the list.
40         - \p Traits - map traits, default is \p skip_list::traits.
41             It is possible to declare option-based list with \p cds::container::skip_list::make_traits metafunction
42             instead of \p Traits template argument.
43
44         Like STL map class, \p %SkipListMap stores its key-value pair as <tt>std:pair< K const, T></tt>.
45
46         @note Before including <tt><cds/container/skip_list_map_rcu.h></tt> you should include appropriate RCU header file,
47         see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files.
48
49         <b>Iterators</b>
50
51         The class supports a forward iterator (\ref iterator and \ref const_iterator).
52         The iteration is ordered.
53         You may iterate over skip-list set items only under RCU lock.
54         Only in this case the iterator is thread-safe since
55         while RCU is locked any set's item cannot be reclaimed.
56
57         The requirement of RCU lock during iterating means that deletion of the elements (i.e. \ref erase)
58         is not possible.
59
60         @warning The iterator object cannot be passed between threads
61
62         The iterator class supports the following minimalistic interface:
63         \code
64         struct iterator {
65             // Default ctor
66             iterator();
67
68             // Copy ctor
69             iterator( iterator const& s);
70
71             value_type * operator ->() const;
72             value_type& operator *() const;
73
74             // Pre-increment
75             iterator& operator ++();
76
77             // Copy assignment
78             iterator& operator = (const iterator& src);
79
80             bool operator ==(iterator const& i ) const;
81             bool operator !=(iterator const& i ) const;
82         };
83         \endcode
84         Note, the iterator object returned by \ref end, \p cend member functions points to \p nullptr and should not be dereferenced.
85
86     */
87     template <
88         typename RCU,
89         typename Key,
90         typename T,
91 #ifdef CDS_DOXYGEN_INVOKED
92         typename Traits = skip_list::traits
93 #else
94         typename Traits
95 #endif
96     >
97     class SkipListMap< cds::urcu::gc< RCU >, Key, T, Traits >:
98 #ifdef CDS_DOXYGEN_INVOKED
99         protected intrusive::SkipListSet< cds::urcu::gc< RCU >, std::pair<Key const, T>, Traits >
100 #else
101         protected details::make_skip_list_map< cds::urcu::gc< RCU >, Key, T, Traits >::type
102 #endif
103     {
104         //@cond
105         typedef details::make_skip_list_map< cds::urcu::gc< RCU >, Key, T, Traits >    maker;
106         typedef typename maker::type base_class;
107         //@endcond
108     public:
109         typedef cds::urcu::gc< RCU > gc; ///< Garbage collector used
110         typedef Key     key_type;       ///< Key type
111         typedef T       mapped_type;    ///< Mapped type
112 #   ifdef CDS_DOXYGEN_INVOKED
113         typedef std::pair< K const, T> value_type;   ///< Value type stored in the map
114 #   else
115         typedef typename maker::value_type  value_type;
116 #   endif
117         typedef Traits  traits;   ///< Map traits
118
119         typedef typename base_class::back_off       back_off;       ///< Back-off strategy used
120         typedef typename traits::allocator          allocator_type; ///< Allocator type used for allocate/deallocate the skip-list nodes
121         typedef typename base_class::item_counter   item_counter;   ///< Item counting policy used
122         typedef typename maker::key_comparator      key_comparator; ///< key comparison functor
123         typedef typename base_class::memory_model   memory_model;   ///< Memory ordering. See cds::opt::memory_model option
124         typedef typename traits::random_level_generator random_level_generator; ///< random level generator
125         typedef typename traits::stat               stat;   ///< internal statistics type
126
127         //@cond
128         typedef cds::container::skip_list::implementation_tag implementation_tag;
129         //@endcond
130
131     protected:
132         //@cond
133         typedef typename maker::node_type           node_type;
134         typedef typename maker::node_allocator      node_allocator;
135
136         typedef std::unique_ptr< node_type, typename maker::node_deallocator >    scoped_node_ptr;
137         //@endcond
138
139     public:
140         typedef typename base_class::rcu_lock  rcu_lock;   ///< RCU scoped lock
141         /// Group of \p extract_xxx functions do not require external locking
142         static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
143
144         /// pointer to extracted node
145         using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_type_traits::disposer >;
146
147     protected:
148         //@cond
149         unsigned int random_level()
150         {
151             return base_class::random_level();
152         }
153
154         value_type * to_value_ptr( node_type * pNode ) const CDS_NOEXCEPT
155         {
156             return pNode ? &pNode->m_Value : nullptr;
157         }
158         //@endcond
159
160     public:
161         /// Default ctor
162         SkipListMap()
163             : base_class()
164         {}
165
166         /// Destructor destroys the set object
167         ~SkipListMap()
168         {}
169
170     public:
171         /// Iterator type
172         typedef skip_list::details::iterator< typename base_class::iterator >  iterator;
173
174         /// Const iterator type
175         typedef skip_list::details::iterator< typename base_class::const_iterator >   const_iterator;
176
177         /// Returns a forward iterator addressing the first element in a map
178         iterator begin()
179         {
180             return iterator( base_class::begin() );
181         }
182
183         /// Returns a forward const iterator addressing the first element in a map
184         const_iterator begin() const
185         {
186             return cbegin();
187         }
188         /// Returns a forward const iterator addressing the first element in a map
189         const_iterator cbegin() const
190         {
191             return const_iterator( base_class::cbegin() );
192         }
193
194         /// Returns a forward iterator that addresses the location succeeding the last element in a map.
195         iterator end()
196         {
197             return iterator( base_class::end() );
198         }
199
200         /// Returns a forward const iterator that addresses the location succeeding the last element in a map.
201         const_iterator end() const
202         {
203             return cend();
204         }
205         /// Returns a forward const iterator that addresses the location succeeding the last element in a map.
206         const_iterator cend() const
207         {
208             return const_iterator( base_class::cend() );
209         }
210
211     public:
212         /// Inserts new node with key and default value
213         /**
214             The function creates a node with \p key and default value, and then inserts the node created into the map.
215
216             Preconditions:
217             - The \p key_type should be constructible from a value of type \p K.
218                 In trivial case, \p K is equal to \p key_type.
219             - The \p mapped_type should be default-constructible.
220
221             RCU \p synchronize method can be called. RCU should not be locked.
222
223             Returns \p true if inserting successful, \p false otherwise.
224         */
225         template <typename K>
226         bool insert( K const& key )
227         {
228             return insert_with( key, [](value_type&){} );
229         }
230
231         /// Inserts new node
232         /**
233             The function creates a node with copy of \p val value
234             and then inserts the node created into the map.
235
236             Preconditions:
237             - The \p key_type should be constructible from \p key of type \p K.
238             - The \p value_type should be constructible from \p val of type \p V.
239
240             RCU \p synchronize method can be called. RCU should not be locked.
241
242             Returns \p true if \p val is inserted into the set, \p false otherwise.
243         */
244         template <typename K, typename V>
245         bool insert( K const& key, V const& val )
246         {
247             scoped_node_ptr pNode( node_allocator().New( random_level(), key, val ));
248             if ( base_class::insert( *pNode ))
249             {
250                 pNode.release();
251                 return true;
252             }
253             return false;
254         }
255
256         /// Inserts new node and initialize it by a functor
257         /**
258             This function inserts new node with key \p key and if inserting is successful then it calls
259             \p func functor with signature
260             \code
261                 struct functor {
262                     void operator()( value_type& item );
263                 };
264             \endcode
265
266             The argument \p item of user-defined functor \p func is the reference
267             to the map's item inserted:
268                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
269                 - <tt>item.second</tt> is a reference to item's value that may be changed.
270
271             The function allows to split creating of new item into three part:
272             - create item from \p key;
273             - insert new item into the map;
274             - if inserting is successful, initialize the value of item by calling \p func functor
275
276             This can be useful if complete initialization of object of \p value_type is heavyweight and
277             it is preferable that the initialization should be completed only if inserting is successful.
278
279             RCU \p synchronize method can be called. RCU should not be locked.
280         */
281         template <typename K, typename Func>
282         bool insert_with( const K& key, Func func )
283         {
284             scoped_node_ptr pNode( node_allocator().New( random_level(), key ));
285             if ( base_class::insert( *pNode, [&func]( node_type& item ) { func( item.m_Value ); } )) {
286                 pNode.release();
287                 return true;
288             }
289             return false;
290         }
291
292         /// For key \p key inserts data of type \p value_type created in-place from \p args
293         /**
294             Returns \p true if inserting successful, \p false otherwise.
295
296             RCU \p synchronize() method can be called. RCU should not be locked.
297         */
298         template <typename K, typename... Args>
299         bool emplace( K&& key, Args&&... args )
300         {
301             scoped_node_ptr pNode( node_allocator().New( random_level(), std::forward<K>(key), std::forward<Args>(args)... ));
302             if ( base_class::insert( *pNode )) {
303                 pNode.release();
304                 return true;
305             }
306             return false;
307         }
308
309         /// Ensures that the \p key exists in the map
310         /**
311             The operation performs inserting or changing data with lock-free manner.
312
313             If the \p key not found in the map, then the new item created from \p key
314             is inserted into the map (note that in this case the \ref key_type should be
315             constructible from type \p K).
316             Otherwise, the functor \p func is called with item found.
317             The functor \p Func interface is:
318             \code
319                 struct my_functor {
320                     void operator()( bool bNew, value_type& item );
321                 };
322             \endcode
323             with arguments:
324             - \p bNew - \p true if the item has been inserted, \p false otherwise
325             - \p item - item of the list
326
327             The functor may change any fields of \p item.second.
328
329             RCU \p synchronize() method can be called. RCU should not be locked.
330
331             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
332             \p second is true if new item has been added or \p false if the item with \p key
333             already is in the list.
334
335             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
336         */
337         template <typename K, typename Func>
338         std::pair<bool, bool> ensure( K const& key, Func func )
339         {
340             scoped_node_ptr pNode( node_allocator().New( random_level(), key ));
341             std::pair<bool, bool> res = base_class::ensure( *pNode,
342                 [&func](bool bNew, node_type& item, node_type const& ){ func( bNew, item.m_Value ); }
343             );
344             if ( res.first && res.second )
345                 pNode.release();
346             return res;
347         }
348
349         /// Delete \p key from the map
350         /**\anchor cds_nonintrusive_SkipListMap_rcu_erase_val
351
352             RCU \p synchronize method can be called. RCU should not be locked.
353
354             Return \p true if \p key is found and deleted, \p false otherwise
355         */
356         template <typename K>
357         bool erase( K const& key )
358         {
359             return base_class::erase(key);
360         }
361
362         /// Deletes the item from the map using \p pred predicate for searching
363         /**
364             The function is an analog of \ref cds_nonintrusive_SkipListMap_rcu_erase_val "erase(K const&)"
365             but \p pred is used for key comparing.
366             \p Less functor has the interface like \p std::less.
367             \p Less must imply the same element order as the comparator used for building the map.
368         */
369         template <typename K, typename Less>
370         bool erase_with( K const& key, Less pred )
371         {
372             CDS_UNUSED( pred );
373             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >());
374         }
375
376         /// Delete \p key from the map
377         /** \anchor cds_nonintrusive_SkipListMap_rcu_erase_func
378
379             The function searches an item with key \p key, calls \p f functor
380             and deletes the item. If \p key is not found, the functor is not called.
381
382             The functor \p Func interface:
383             \code
384             struct extractor {
385                 void operator()(value_type& item) { ... }
386             };
387             \endcode
388
389             RCU \p synchronize method can be called. RCU should not be locked.
390
391             Return \p true if key is found and deleted, \p false otherwise
392         */
393         template <typename K, typename Func>
394         bool erase( K const& key, Func f )
395         {
396             return base_class::erase( key, [&f]( node_type& node) { f( node.m_Value ); } );
397         }
398
399         /// Deletes the item from the map using \p pred predicate for searching
400         /**
401             The function is an analog of \ref cds_nonintrusive_SkipListMap_rcu_erase_func "erase(K const&, Func)"
402             but \p pred is used for key comparing.
403             \p Less functor has the interface like \p std::less.
404             \p Less must imply the same element order as the comparator used for building the map.
405         */
406         template <typename K, typename Less, typename Func>
407         bool erase_with( K const& key, Less pred, Func f )
408         {
409             CDS_UNUSED( pred );
410             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(),
411                 [&f]( node_type& node) { f( node.m_Value ); } );
412         }
413
414         /// Extracts the item from the map with specified \p key
415         /** \anchor cds_nonintrusive_SkipListMap_rcu_extract
416             The function searches an item with key equal to \p key in the map,
417             unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
418             If the item is not found the function returns an empty \p exempt_ptr
419
420             Note the compare functor from \p Traits class' template argument
421             should accept a parameter of type \p K that can be not the same as \p key_type.
422
423             RCU \p synchronize() method can be called. RCU should NOT be locked.
424
425             The function does not free the item found.
426             The item will be implicitly freed when the returned object is destroyed or when
427             its \p release() member function is called.
428         */
429         template <typename K>
430         exempt_ptr extract( K const& key )
431         {
432             return exempt_ptr( base_class::do_extract( key ));
433         }
434
435         /// Extracts the item from the map with comparing functor \p pred
436         /**
437             The function is an analog of \p extract(K const&) but \p pred predicate is used for key comparing.
438             \p Less has the semantics like \p std::less.
439             \p pred must imply the same element order as the comparator used for building the map.
440         */
441         template <typename K, typename Less>
442         exempt_ptr extract_with( K const& key, Less pred )
443         {
444             CDS_UNUSED( pred );
445             return exempt_ptr( base_class::do_extract_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >()));
446         }
447
448         /// Extracts an item with minimal key from the map
449         /**
450             The function searches an item with minimal key, unlinks it,
451             and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
452             If the skip-list is empty the function returns an empty \p exempt_ptr.
453
454             RCU \p synchronize method can be called. RCU should NOT be locked.
455
456             The function does not free the item found.
457             The item will be implicitly freed when the returned object is destroyed or when
458             its \p release() member function is called.
459         */
460         exempt_ptr extract_min()
461         {
462             return exempt_ptr( base_class::do_extract_min());
463         }
464
465         /// Extracts an item with maximal key from the map
466         /**
467             The function searches an item with maximal key, unlinks it from the set,
468             and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
469             If the skip-list is empty the function returns an empty \p exempt_ptr.
470
471             RCU \p synchronize method can be called. RCU should NOT be locked.
472
473             The function does not free the item found.
474             The item will be implicitly freed when the returned object is destroyed or when
475             its \p release() member function is called.
476             */
477         exempt_ptr extract_max()
478         {
479             return exempt_ptr( base_class::do_extract_max());
480         }
481
482         /// Find the key \p key
483         /** \anchor cds_nonintrusive_SkipListMap_rcu_find_cfunc
484
485             The function searches the item with key equal to \p key and calls the functor \p f for item found.
486             The interface of \p Func functor is:
487             \code
488             struct functor {
489                 void operator()( value_type& item );
490             };
491             \endcode
492             where \p item is the item found.
493
494             The functor may change \p item.second.
495
496             The function applies RCU lock internally.
497
498             The function returns \p true if \p key is found, \p false otherwise.
499         */
500         template <typename K, typename Func>
501         bool find( K const& key, Func f )
502         {
503             return base_class::find( key, [&f](node_type& item, K const& ) { f( item.m_Value );});
504         }
505
506         /// Finds the key \p val using \p pred predicate for searching
507         /**
508             The function is an analog of \ref cds_nonintrusive_SkipListMap_rcu_find_cfunc "find(K const&, Func)"
509             but \p pred is used for key comparing.
510             \p Less functor has the interface like \p std::less.
511             \p Less must imply the same element order as the comparator used for building the map.
512         */
513         template <typename K, typename Less, typename Func>
514         bool find_with( K const& key, Less pred, Func f )
515         {
516             CDS_UNUSED( pred );
517             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(),
518                 [&f](node_type& item, K const& ) { f( item.m_Value );});
519         }
520
521         /// Find the key \p key
522         /** \anchor cds_nonintrusive_SkipListMap_rcu_find_val
523
524             The function searches the item with key equal to \p key
525             and returns \p true if it is found, and \p false otherwise.
526
527             The function applies RCU lock internally.
528         */
529         template <typename K>
530         bool find( K const& key )
531         {
532             return base_class::find( key );
533         }
534
535         /// Finds the key \p val using \p pred predicate for searching
536         /**
537             The function is an analog of \ref cds_nonintrusive_SkipListMap_rcu_find_val "find(K const&)"
538             but \p pred is used for key comparing.
539             \p Less functor has the interface like \p std::less.
540             \p Less must imply the same element order as the comparator used for building the map.
541         */
542         template <typename K, typename Less>
543         bool find_with( K const& key, Less pred )
544         {
545             CDS_UNUSED( pred );
546             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >() );
547         }
548
549         /// Finds the key \p key and return the item found
550         /** \anchor cds_nonintrusive_SkipListMap_rcu_get
551             The function searches the item with key equal to \p key and returns the pointer to item found.
552             If \p key is not found it returns \p nullptr.
553
554             Note the compare functor in \p Traits class' template argument
555             should accept a parameter of type \p K that can be not the same as \p key_type.
556
557             RCU should be locked before call of this function.
558             Returned item is valid only while RCU is locked:
559             \code
560             typedef cds::container::SkipListMap< cds::urcu::gc< cds::urcu::general_buffered<> >, int, foo, my_traits > skip_list;
561             skip_list theList;
562             // ...
563             {
564                 // Lock RCU
565                 skip_list::rcu_lock lock;
566
567                 skip_list::value_type * pVal = theList.get( 5 );
568                 // Deal with pVal
569                 //...
570
571                 // Unlock RCU by rcu_lock destructor
572                 // pVal can be freed at any time after RCU unlocking
573             }
574             \endcode
575
576             After RCU unlocking the \p %force_dispose member function can be called manually,
577             see \ref force_dispose for explanation.
578         */
579         template <typename K>
580         value_type * get( K const& key )
581         {
582             return to_value_ptr( base_class::get( key ));
583         }
584
585         /// Finds the key \p key and return the item found
586         /**
587             The function is an analog of \ref cds_nonintrusive_SkipListMap_rcu_get "get(K const&)"
588             but \p pred is used for comparing the keys.
589
590             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
591             in any order.
592             \p pred must imply the same element order as the comparator used for building the map.
593         */
594         template <typename K, typename Less>
595         value_type * get_with( K const& key, Less pred )
596         {
597             CDS_UNUSED( pred );
598             return to_value_ptr( base_class::get_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >() ));
599         }
600
601         /// Clears the map (not atomic)
602         void clear()
603         {
604             base_class::clear();
605         }
606
607         /// Checks if the map is empty
608         /**
609             Emptiness is checked by item counting: if item count is zero then the map is empty.
610         */
611         bool empty() const
612         {
613             return base_class::empty();
614         }
615
616         /// Returns item count in the map
617         size_t size() const
618         {
619             return base_class::size();
620         }
621
622         /// Returns const reference to internal statistics
623         stat const& statistics() const
624         {
625             return base_class::statistics();
626         }
627
628         /// Clears internal list of ready-to-delete items passing them to RCU reclamation cycle
629         /** @copydetails cds_intrusive_SkipListSet_rcu_force_dispose
630         */
631         void force_dispose()
632         {
633             return base_class::force_dispose();
634         }
635     };
636 }} // namespace cds::container
637
638 #endif // #ifndef CDSLIB_CONTAINER_SKIP_LIST_MAP_RCU_H