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