FCStack refactoring
[libcds.git] / cds / container / split_list_map_rcu.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_SPLIT_LIST_MAP_RCU_H
4 #define __CDS_CONTAINER_SPLIT_LIST_MAP_RCU_H
5
6 #include <cds/container/split_list_set_rcu.h>
7 #include <cds/details/binary_functor_wrapper.h>
8
9 namespace cds { namespace container {
10
11     /// Split-ordered list map (template specialization for \ref cds_urcu_desc "RCU")
12     /** @ingroup cds_nonintrusive_map
13         \anchor cds_nonintrusive_SplitListMap_rcu
14
15         Hash table implementation based on split-ordered list algorithm discovered by Ori Shalev and Nir Shavit, see
16         - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables"
17         - [2008] Nir Shavit "The Art of Multiprocessor Programming"
18
19         See intrusive::SplitListSet for a brief description of the split-list algorithm.
20
21         Template parameters:
22         - \p RCU - one of \ref cds_urcu_gc "RCU type"
23         - \p Key - key type of an item stored in the map. It should be copy-constructible
24         - \p Value - value type stored in the map
25         - \p Traits - type traits, default is split_list::type_traits. Instead of declaring split_list::type_traits -based
26             struct you may apply option-based notation with split_list::make_traits metafunction.
27
28         <b>Iterators</b>
29
30         The class supports a forward iterator (\ref iterator and \ref const_iterator).
31         The iteration is unordered.
32
33         You may iterate over split-list map items only under RCU lock.
34         Only in this case the iterator is thread-safe since
35         while RCU is locked any map's item cannot be reclaimed.
36
37         The requirement of RCU lock during iterating means that deletion of the elements (i.e. \ref erase)
38         is not possible.
39
40         @warning The iterator object cannot be passed between threads
41
42         \warning Due to concurrent nature of split-list map it is not guarantee that you can iterate
43         all elements in the map: any concurrent deletion can exclude the element
44         pointed by the iterator from the map, and your iteration can be terminated
45         before end of the map. Therefore, such iteration is more suitable for debugging purposes
46
47         The iterator class supports the following minimalistic interface:
48         \code
49         struct iterator {
50             // Default ctor
51             iterator();
52
53             // Copy ctor
54             iterator( iterator const& s);
55
56             value_type * operator ->() const;
57             value_type& operator *() const;
58
59             // Pre-increment
60             iterator& operator ++();
61
62             // Copy assignment
63             iterator& operator = (const iterator& src);
64
65             bool operator ==(iterator const& i ) const;
66             bool operator !=(iterator const& i ) const;
67         };
68         \endcode
69         Note, the iterator object returned by \ref end, \p cend member functions points to \p nullptr and should not be dereferenced.
70
71         \par Usage
72
73         You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list
74         is original data structure based on an ordered list. Suppose, you want construct split-list map based on cds::urcu::general_buffered<> GC
75         and MichaelList as ordered list implementation. Your map should map \p int key to <tt>std::string</tt> value.
76         So, you beginning your program with following include:
77         \code
78         #include <cds/urcu/general_buffered.h>
79         #include <cds/container/michael_list_rcu.h>
80         #include <cds/container/split_list_map_rcu.h>
81
82         namespace cc = cds::container;
83         \endcode
84         The inclusion order is important:
85         - first, include one of \ref cds_urcu_gc "RCU implementation" (<tt>cds/urcu/general_buffered.h</tt> in our case)
86         - second, include file for ordered-list implementation (for this example, <tt>cds/container/michael_list_rcu.h</tt>),
87         - then, the header for RCU-based split-list map <tt>cds/container/split_list_map_rcu.h</tt>.
88
89         Now, you should declare traits for split-list map. The main parts of traits are a hash functor for the map key and a comparing functor for ordered list.
90         We use <tt>std::hash<int></tt> as hash functor and <tt>std::less<int></tt> predicate as comparing functor.
91
92         The second attention: instead of using %MichaelList in %SplitListMap traits we use a tag <tt>cds::contaner::michael_list_tag</tt>
93         for the Michael's list.
94         The split-list requires significant support from underlying ordered list class and it is not good idea to dive you
95         into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface.
96
97         \code
98         // SplitListMap traits
99         struct foo_set_traits: public cc::split_list::type_traits
100         {
101             typedef cc::michael_list_tag   ordered_list    ;   // what type of ordered list we want to use
102             typedef std::hash<int>         hash            ;   // hash functor for the key stored in split-list map
103
104             // Type traits for our MichaelList class
105             struct ordered_list_traits: public cc::michael_list::type_traits
106             {
107                 typedef std::less<int> less   ;   // use our std::less predicate as comparator to order list nodes
108             };
109         };
110         \endcode
111
112         Now you are ready to declare our map class based on \p %SplitListMap:
113         \code
114         typedef cc::SplitListMap< cds::urcu::gc<cds::urcu::general_buffered<> >, int, std::string, foo_set_traits > int_string_map;
115         \endcode
116
117         You may use the modern option-based declaration instead of classic type-traits-based one:
118         \code
119         typedef cc:SplitListMap<
120             cds::urcu::gc<cds::urcu::general_buffered<> >  // RCU type
121             ,int                    // key type
122             ,std::string            // value type
123             ,cc::split_list::make_traits<      // metafunction to build split-list traits
124                 cc::split_list::ordered_list<cc::michael_list_tag>     // tag for underlying ordered list implementation
125                 ,cc::opt::hash< std::hash<int> >        // hash functor
126                 ,cc::split_list::ordered_list_traits<    // ordered list traits desired
127                     cc::michael_list::make_traits<    // metafunction to build lazy list traits
128                         cc::opt::less< std::less<int> >         // less-based compare functor
129                     >::type
130                 >
131             >::type
132         >  int_string_map;
133         \endcode
134         In case of option-based declaration using split_list::make_traits metafunction the struct \p foo_set_traits is not required.
135
136         Now, the map of type \p int_string_map is ready to use in your program.
137
138         Note that in this example we show only mandatory type_traits parts, optional ones is the default and they are inherited
139         from cds::container::split_list::type_traits.
140         The <b>cds</b> library contains many other options for deep tuning of behavior of the split-list and
141         ordered-list containers.
142     */
143     template <
144         class RCU,
145         typename Key,
146         typename Value,
147 #ifdef CDS_DOXYGEN_INVOKED
148         class Traits = split_list::type_traits
149 #else
150         class Traits
151 #endif
152     >
153     class SplitListMap< cds::urcu::gc< RCU >, Key, Value, Traits >:
154         protected container::SplitListSet<
155             cds::urcu::gc< RCU >,
156             std::pair<Key const, Value>,
157             split_list::details::wrap_map_traits<Key, Value, Traits>
158         >
159     {
160         //@cond
161         typedef container::SplitListSet<
162             cds::urcu::gc< RCU >,
163             std::pair<Key const, Value>,
164             split_list::details::wrap_map_traits<Key, Value, Traits>
165         >  base_class;
166         //@endcond
167
168     public:
169         typedef typename base_class::gc gc              ;   ///< Garbage collector
170         typedef Traits                  options         ;   ///< ]p Traits template argument
171         typedef Key                     key_type        ;   ///< key type
172         typedef Value                   mapped_type     ;   ///< type of value stored in the map
173
174         typedef std::pair<key_type const, mapped_type>  value_type  ;   ///< key-value pair type
175         typedef typename base_class::ordered_list       ordered_list;   ///< Underlying ordered list class
176         typedef typename base_class::key_comparator     key_comparator  ;   ///< key comparison functor
177
178         typedef typename base_class::hash           hash            ;   ///< Hash functor for \ref key_type
179         typedef typename base_class::item_counter   item_counter    ;   ///< Item counter type
180
181         typedef typename base_class::rcu_lock       rcu_lock    ; ///< RCU scoped lock
182         typedef typename base_class::exempt_ptr     exempt_ptr  ; ///< pointer to extracted node
183         /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
184         static CDS_CONSTEXPR_CONST bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
185
186     protected:
187         //@cond
188         typedef typename base_class::maker::type_traits::key_accessor key_accessor;
189         //@endcond
190
191     public:
192         /// Forward iterator
193         typedef typename base_class::iterator iterator;
194
195         /// Const forward iterator
196         typedef typename base_class::const_iterator const_iterator;
197
198         /// Returns a forward iterator addressing the first element in a map
199         /**
200             For empty map \code begin() == end() \endcode
201         */
202         iterator begin()
203         {
204             return base_class::begin();
205         }
206
207         /// Returns an iterator that addresses the location succeeding the last element in a map
208         /**
209             Do not use the value returned by <tt>end</tt> function to access any item.
210             The returned value can be used only to control reaching the end of the map.
211             For empty map \code begin() == end() \endcode
212         */
213         iterator end()
214         {
215             return base_class::end();
216         }
217
218         /// Returns a forward const iterator addressing the first element in a map
219         //@{
220         const_iterator begin() const
221         {
222             return base_class::begin();
223         }
224         const_iterator cbegin()
225         {
226             return base_class::cbegin();
227         }
228         //@}
229
230         /// Returns an const iterator that addresses the location succeeding the last element in a map
231         //@{
232         const_iterator end() const
233         {
234             return base_class::end();
235         }
236         const_iterator cend()
237         {
238             return base_class::cend();
239         }
240         //@}
241
242     public:
243         /// Initializes split-ordered map of default capacity
244         /**
245             The default capacity is defined in bucket table constructor.
246             See intrusive::split_list::expandable_bucket_table, intrusive::split_list::static_bucket_table
247             which selects by intrusive::split_list::dynamic_bucket_table option.
248         */
249         SplitListMap()
250             : base_class()
251         {}
252
253         /// Initializes split-ordered map
254         SplitListMap(
255             size_t nItemCount           ///< estimate average item count
256             , size_t nLoadFactor = 1    ///< load factor - average item count per bucket. Small integer up to 10, default is 1.
257             )
258             : base_class( nItemCount, nLoadFactor )
259         {}
260
261     public:
262         /// Inserts new node with key and default value
263         /**
264             The function creates a node with \p key and default value, and then inserts the node created into the map.
265
266             Preconditions:
267             - The \ref key_type should be constructible from value of type \p K.
268                 In trivial case, \p K is equal to \ref key_type.
269             - The \ref mapped_type should be default-constructible.
270
271             The function applies RCU lock internally.
272
273             Returns \p true if inserting successful, \p false otherwise.
274         */
275         template <typename K>
276         bool insert( K const& key )
277         {
278             //TODO: pass arguments by reference (make_pair makes copy)
279             return base_class::insert( std::make_pair( key, mapped_type() ) );
280         }
281
282         /// Inserts new node
283         /**
284             The function creates a node with copy of \p val value
285             and then inserts the node created into the map.
286
287             Preconditions:
288             - The \ref key_type should be constructible from \p key of type \p K.
289             - The \ref mapped_type should be constructible from \p val of type \p V.
290
291             The function applies RCU lock internally.
292
293             Returns \p true if \p val is inserted into the map, \p false otherwise.
294         */
295         template <typename K, typename V>
296         bool insert( K const& key, V const& val )
297         {
298             //TODO: pass arguments by reference (make_pair makes copy)
299             return base_class::insert( std::make_pair(key, val) );
300         }
301
302         /// Inserts new node and initialize it by a functor
303         /**
304             This function inserts new node with key \p key and if inserting is successful then it calls
305             \p func functor with signature
306             \code
307                 struct functor {
308                     void operator()( value_type& item );
309                 };
310             \endcode
311
312             The argument \p item of user-defined functor \p func is the reference
313             to the map's item inserted:
314                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
315                 - <tt>item.second</tt> is a reference to item's value that may be changed.
316
317             It should be keep in mind that concurrent modifications of \p <tt>item.second</tt> may be possible.
318             User-defined functor \p func should guarantee that during changing item's value no any other changes
319             could be made on this \p item by concurrent threads.
320
321             The user-defined functor can be passed by reference using \p std::ref
322             and it is called only if inserting is successful.
323
324             The key_type should be constructible from value of type \p K.
325
326             The function allows to split creating of new item into two part:
327             - create item from \p key;
328             - insert new item into the map;
329             - if inserting is successful, initialize the value of item by calling \p func functor
330
331             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
332             it is preferable that the initialization should be completed only if inserting is successful.
333
334             The function applies RCU lock internally.
335         */
336         template <typename K, typename Func>
337         bool insert_key( K const& key, Func func )
338         {
339             //TODO: pass arguments by reference (make_pair makes copy)
340             return base_class::insert( std::make_pair( key, mapped_type() ), func );
341         }
342
343         /// For key \p key inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
344         /**
345             \p key_type should be constructible from type \p K
346
347             The function applies RCU lock internally.
348
349             Returns \p true if inserting successful, \p false otherwise.
350         */
351         template <typename K, typename... Args>
352         bool emplace( K&& key, Args&&... args )
353         {
354             return base_class::emplace( std::forward<K>(key), std::move(mapped_type(std::forward<Args>(args)...)));
355         }
356
357         /// Ensures that the \p key exists in the map
358         /**
359             The operation performs inserting or changing data with lock-free manner.
360
361             If the \p key not found in the map, then the new item created from \p key
362             is inserted into the map (note that in this case the \ref key_type should be
363             constructible from type \p K).
364             Otherwise, the functor \p func is called with item found.
365             The functor \p Func may be a function with signature:
366             \code
367                 void func( bool bNew, value_type& item );
368             \endcode
369             or a functor:
370             \code
371                 struct my_functor {
372                     void operator()( bool bNew, value_type& item );
373                 };
374             \endcode
375
376             with arguments:
377             - \p bNew - \p true if the item has been inserted, \p false otherwise
378             - \p item - item of the list
379
380             The functor may change any fields of the \p item.second that is \ref mapped_type;
381             however, \p func must guarantee that during changing no any other modifications
382             could be made on this item by concurrent threads.
383
384             You may pass \p func argument by reference using \p std::ref
385
386             The function applies RCU lock internally.
387
388             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
389             \p second is true if new item has been added or \p false if the item with \p key
390             already is in the list.
391         */
392         template <typename K, typename Func>
393         std::pair<bool, bool> ensure( K const& key, Func func )
394         {
395             //TODO: pass arguments by reference (make_pair makes copy)
396             return base_class::ensure( std::make_pair( key, mapped_type() ),
397                 [&func](bool bNew, value_type& item, value_type const& /*val*/) {
398                     func( bNew, item );
399                 } );
400         }
401
402         /// Deletes \p key from the map
403         /** \anchor cds_nonintrusive_SplitListMap_rcu_erase_val
404
405             RCU \p synchronize method can be called. RCU should not be locked.
406
407             Return \p true if \p key is found and deleted, \p false otherwise
408         */
409         template <typename K>
410         bool erase( K const& key )
411         {
412             return base_class::erase( key );
413         }
414
415         /// Deletes the item from the map using \p pred predicate for searching
416         /**
417             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_erase_val "erase(K const&)"
418             but \p pred is used for key comparing.
419             \p Less functor has the interface like \p std::less.
420             \p Less must imply the same element order as the comparator used for building the map.
421         */
422         template <typename K, typename Less>
423         bool erase_with( K const& key, Less pred )
424         {
425             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
426         }
427
428         /// Deletes \p key from the map
429         /** \anchor cds_nonintrusive_SplitListMap_rcu_erase_func
430
431             The function searches an item with key \p key, calls \p f functor
432             and deletes the item. If \p key is not found, the functor is not called.
433
434             The functor \p Func interface is:
435             \code
436             struct extractor {
437                 void operator()(value_type& item) { ... }
438             };
439             \endcode
440             The functor may be passed by reference using <tt>boost:ref</tt>
441
442             RCU \p synchronize method can be called. RCU should not be locked.
443
444             Return \p true if key is found and deleted, \p false otherwise
445         */
446         template <typename K, typename Func>
447         bool erase( K const& key, Func f )
448         {
449             return base_class::erase( key, f );
450         }
451
452         /// Deletes the item from the map using \p pred predicate for searching
453         /**
454             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_erase_func "erase(K const&, Func)"
455             but \p pred is used for key comparing.
456             \p Less functor has the interface like \p std::less.
457             \p Less must imply the same element order as the comparator used for building the map.
458         */
459         template <typename K, typename Less, typename Func>
460         bool erase_with( K const& key, Less pred, Func f )
461         {
462             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>(), f );
463         }
464
465         /// Extracts an item from the map
466         /** \anchor cds_nonintrusive_SplitListMap_rcu_extract
467             The function searches an item with key equal to \p key in the map,
468             unlinks it from the map, places item pointer into \p dest argument, and returns \p true.
469             If the item with the key equal to \p key is not found the function return \p false.
470
471             @note The function does NOT call RCU read-side lock or synchronization,
472             and does NOT dispose the item found. It just excludes the item from the map
473             and returns a pointer to item found.
474             You should lock RCU before calling of the function, and you should synchronize RCU
475             outside the RCU lock to free extracted item
476
477             \code
478             typedef cds::urcu::gc< general_buffered<> > rcu;
479             typedef cds::container::SplitListMap< rcu, int, Foo > splitlist_map;
480
481             splitlist_map theMap;
482             // ...
483
484             typename splitlist_map::exempt_ptr p;
485             {
486                 // first, we should lock RCU
487                 typename splitlist_map::rcu_lock lock;
488
489                 // Now, you can apply extract function
490                 // Note that you must not delete the item found inside the RCU lock
491                 if ( theMap.extract( p, 10 )) {
492                     // do something with p
493                     ...
494                 }
495             }
496
497             // We may safely release p here
498             // release() passes the pointer to RCU reclamation cycle
499             p.release();
500             \endcode
501         */
502         template <typename K>
503         bool extract( exempt_ptr& dest, K const& key )
504         {
505             return base_class::extract( dest, key );
506         }
507
508         /// Extracts an item from the map using \p pred predicate for searching
509         /**
510             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_extract "extract(exempt_ptr&, K const&)"
511             but \p pred is used for key comparing.
512             \p Less functor has the interface like \p std::less.
513             \p pred must imply the same element order as the comparator used for building the map.
514         */
515         template <typename K, typename Less>
516         bool extract_with( exempt_ptr& dest, K const& key, Less pred )
517         {
518             return base_class::extract_with( dest, key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
519         }
520
521         /// Finds the key \p key
522         /** \anchor cds_nonintrusive_SplitListMap_rcu_find_cfunc
523
524             The function searches the item with key equal to \p key and calls the functor \p f for item found.
525             The interface of \p Func functor is:
526             \code
527             struct functor {
528                 void operator()( value_type& item );
529             };
530             \endcode
531             where \p item is the item found.
532
533             You may pass \p f argument by reference using \p std::ref.
534
535             The functor may change \p item.second. Note that the functor is only guarantee
536             that \p item cannot be disposed during functor is executing.
537             The functor does not serialize simultaneous access to the map's \p item. If such access is
538             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
539
540             The function applies RCU lock internally.
541
542             The function returns \p true if \p key is found, \p false otherwise.
543         */
544         template <typename K, typename Func>
545         bool find( K const& key, Func f )
546         {
547             return base_class::find( key, [&f](value_type& pair, K const&){ f( pair ); } );
548         }
549
550         /// Finds the key \p key using \p pred predicate for searching
551         /**
552             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_find_cfunc "find(K const&, Func)"
553             but \p pred is used for key comparing.
554             \p Less functor has the interface like \p std::less.
555             \p Less must imply the same element order as the comparator used for building the map.
556         */
557         template <typename K, typename Less, typename Func>
558         bool find_with( K const& key, Less pred, Func f )
559         {
560             return base_class::find_with( key,
561                 cds::details::predicate_wrapper<value_type, Less, key_accessor>(),
562                 [&f](value_type& pair, K const&){ f( pair ); } );
563         }
564
565         /// Finds the key \p key
566         /** \anchor cds_nonintrusive_SplitListMap_rcu_find_val
567
568             The function searches the item with key equal to \p key
569             and returns \p true if it is found, and \p false otherwise.
570
571             The function applies RCU lock internally.
572         */
573         template <typename K>
574         bool find( K const& key )
575         {
576             return base_class::find( key );
577         }
578
579         /// Finds the key \p key using \p pred predicate for searching
580         /**
581             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_find_val "find(K const&)"
582             but \p pred is used for key comparing.
583             \p Less functor has the interface like \p std::less.
584             \p Less must imply the same element order as the comparator used for building the map.
585         */
586         template <typename K, typename Less>
587         bool find_with( K const& key, Less pred )
588         {
589             return base_class::find_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
590         }
591
592         /// Finds \p key and return the item found
593         /** \anchor cds_intrusive_SplitListMap_rcu_get
594             The function searches the item with key equal to \p key and returns the pointer to item found.
595             If \p key is not found it returns \p nullptr.
596
597             Note the compare functor should accept a parameter of type \p K that can be not the same as \p value_type.
598
599             RCU should be locked before call of this function.
600             Returned item is valid only while RCU is locked:
601             \code
602             typedef cds::urcu::gc< general_buffered<> > rcu;
603             typedef cds::container::SplitListMap< rcu, int, Foo > splitlist_map;
604             splitlist_map theMap;
605             // ...
606             {
607                 // Lock RCU
608                 typename splitlist_map::rcu_lock lock;
609
610                 typename splitlist_map::value_type * pVal = theMap.get( 5 );
611                 if ( pVal ) {
612                     // Deal with pVal
613                     //...
614                 }
615                 // Unlock RCU by rcu_lock destructor
616                 // pVal can be retired by disposer at any time after RCU has been unlocked
617             }
618             \endcode
619         */
620         template <typename K>
621         value_type * get( K const& key )
622         {
623             return base_class::get( key );
624         }
625
626         /// Finds \p key with predicate specified and return the item found
627         /**
628             The function is an analog of \ref cds_intrusive_SplitListMap_rcu_get "get(K const&)"
629             but \p pred is used for comparing the keys.
630
631             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
632             in any order.
633             \p pred must imply the same element order as the comparator used for building the map.
634         */
635         template <typename K, typename Less>
636         value_type * get_with( K const& key, Less pred )
637         {
638             return base_class::get_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
639         }
640
641         /// Clears the map (non-atomic)
642         /**
643             The function unlink all items from the map.
644             The function is not atomic and not lock-free and should be used for debugging only.
645
646             RCU \p synchronize method can be called. RCU should not be locked.
647         */
648         void clear()
649         {
650             base_class::clear();
651         }
652
653         /// Checks if the map is empty
654         /**
655             Emptiness is checked by item counting: if item count is zero then the map is empty.
656             Thus, the correct item counting is an important part of the map implementation.
657         */
658         bool empty() const
659         {
660             return base_class::empty();
661         }
662
663         /// Returns item count in the map
664         size_t size() const
665         {
666             return base_class::size();
667         }
668     };
669
670
671 }} // namespace cds::container
672
673 #endif // #ifndef __CDS_CONTAINER_SPLIT_LIST_MAP_RCU_H