fixed adding file problem
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / libcds-2.3.2 / cds / container / lazy_list_rcu.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_LAZY_LIST_RCU_H
32 #define CDSLIB_CONTAINER_LAZY_LIST_RCU_H
33
34 #include <memory>
35 #include <cds/container/details/lazy_list_base.h>
36 #include <cds/intrusive/lazy_list_rcu.h>
37 #include <cds/details/binary_functor_wrapper.h>
38 #include <cds/container/details/make_lazy_list.h>
39
40 namespace cds { namespace container {
41
42     /// Lazy ordered list (template specialization for \ref cds_urcu_desc "RCU")
43     /** @ingroup cds_nonintrusive_list
44         \anchor cds_nonintrusive_LazyList_rcu
45
46         Usually, ordered single-linked list is used as a building block for the hash table implementation.
47         The complexity of searching is <tt>O(N)</tt>.
48
49         Source:
50         - [2005] Steve Heller, Maurice Herlihy, Victor Luchangco, Mark Moir, William N. Scherer III, and Nir Shavit
51             "A Lazy Concurrent List-Based Set Algorithm"
52
53         The lazy list is based on an optimistic locking scheme for inserts and removes,
54         eliminating the need to use the equivalent of an atomically markable
55         reference. It also has a novel wait-free membership \p find operation
56         that does not need to perform cleanup operations and is more efficient.
57
58         It is non-intrusive version of \p cds::intrusive::LazyList class
59
60         Template arguments:
61         - \p RCU - one of \ref cds_urcu_gc "RCU type"
62         - \p T - type to be stored in the list.
63         - \p Traits - type traits, default is lazy_list::traits
64             It is possible to declare option-based list with cds::container::lazy_list::make_traits metafunction istead of \p Traits template
65             argument. For example, the following traits-based declaration of \p gc::HP lazy list
66             \code
67             #include <cds/urcu/general_instant.h>
68             #include <cds/container/lazy_list_rcu.h>
69             // Declare comparator for the item
70             struct my_compare {
71                 int operator ()( int i1, int i2 )
72                 {
73                     return i1 - i2;
74                 }
75             };
76
77             // Declare traits
78             struct my_traits: public cds::container::lazy_list::traits
79             {
80                 typedef my_compare compare;
81             };
82
83             // Declare traits-based list
84             typedef cds::container::LazyList< cds::urcu::gc< cds::urcu::general_instant<> >, int, my_traits > traits_based_list;
85             \endcode
86             is equal to the following option-based list
87             \code
88             #include <cds/urcu/general_instant.h>
89             #include <cds/container/lazy_list_rcu.h>
90
91             // my_compare is the same
92
93             // Declare option-based list
94             typedef cds::container::LazyList< cds::urcu::gc< cds::urcu::general_instant<> >, int,
95                 typename cds::container::lazy_list::make_traits<
96                     cds::container::opt::compare< my_compare >     // item comparator option
97                 >::type
98             >     option_based_list;
99             \endcode
100
101         The implementation does not divide type \p T into key and value part and
102         may be used as main building block for some hash set containers.
103         The key is a function (or a part) of type \p T, and this function is specified by \p Traits::compare functor
104         or \p Traits::less predicate
105
106         \ref cds_nonintrusive_LazyKVList_rcu "LazyKVList" is a key-value version
107         of lazy non-intrusive list that is closer to the C++ std library approach.
108
109         @note Before including <tt><cds/container/lazy_list_rcu.h></tt> you should include
110         appropriate RCU header file, see \ref cds_urcu_gc "RCU type" for list
111         of existing RCU class and corresponding header files.
112     */
113     template <
114         typename RCU,
115         typename T,
116 #ifdef CDS_DOXYGEN_INVOKED
117         typename Traits = lazy_list::traits
118 #else
119         typename Traits
120 #endif
121     >
122     class LazyList< cds::urcu::gc<RCU>, T, Traits >:
123 #ifdef CDS_DOXYGEN_INVOKED
124         protected intrusive::LazyList< cds::urcu::gc<RCU>, T, Traits >
125 #else
126         protected details::make_lazy_list< cds::urcu::gc<RCU>, T, Traits >::type
127 #endif
128     {
129         //@cond
130         typedef details::make_lazy_list< cds::urcu::gc<RCU>, T, Traits > maker;
131         typedef typename maker::type  base_class;
132         //@endcond
133
134     public:
135         typedef cds::urcu::gc<RCU> gc; ///< Garbage collector
136         typedef T value_type;          ///< Type of value stored in the list
137         typedef Traits traits;         ///< List traits
138
139         typedef typename base_class::back_off     back_off;       ///< Back-off strategy
140         typedef typename maker::allocator_type    allocator_type; ///< Allocator type used for allocate/deallocate the nodes
141         typedef typename base_class::item_counter item_counter;   ///< Item counting policy used
142         typedef typename maker::key_comparator    key_comparator; ///< key compare functor
143         typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See cds::opt::memory_model option
144         typedef typename base_class::stat         stat;           ///< Internal statistics
145         typedef typename base_class::rcu_check_deadlock rcu_check_deadlock; ///< Deadlock checking policy
146
147         typedef typename gc::scoped_lock  rcu_lock ;  ///< RCU scoped lock
148         static constexpr const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal; ///< Group of \p extract_xxx functions require external locking
149
150         //@cond
151         // Rebind traits (split-list support)
152         template <typename... Options>
153         struct rebind_traits {
154             typedef LazyList<
155                 gc
156                 , value_type
157                 , typename cds::opt::make_options< traits, Options...>::type
158             > type;
159         };
160
161         // Stat selector
162         template <typename Stat>
163         using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >;
164         //@endcond
165
166     protected:
167         //@cond
168         typedef typename base_class::value_type     node_type;
169         typedef typename maker::cxx_allocator       cxx_allocator;
170         typedef typename maker::node_deallocator    node_deallocator;
171         typedef typename maker::intrusive_traits::compare intrusive_key_comparator;
172
173         typedef typename base_class::node_type head_type;
174
175         struct node_disposer {
176             void operator()( node_type * pNode )
177             {
178                 free_node( pNode );
179             }
180         };
181         typedef std::unique_ptr< node_type, node_disposer >     scoped_node_ptr;
182         //@endcond
183
184     public:
185         using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer >; ///< pointer to extracted node
186         /// Type of \p get() member function return value
187         typedef value_type * raw_ptr;
188
189     protected:
190         //@cond
191         template <bool IsConst>
192         class iterator_type: protected base_class::template iterator_type<IsConst>
193         {
194             typedef typename base_class::template iterator_type<IsConst>    iterator_base;
195
196             iterator_type( head_type const& pNode )
197                 : iterator_base( const_cast<head_type *>( &pNode ))
198             {}
199
200             iterator_type( head_type const * pNode )
201                 : iterator_base( const_cast<head_type *>( pNode ))
202             {}
203
204             friend class LazyList;
205
206         public:
207             typedef typename cds::details::make_const_type<value_type, IsConst>::pointer   value_ptr;
208             typedef typename cds::details::make_const_type<value_type, IsConst>::reference value_ref;
209
210             iterator_type()
211             {}
212
213             iterator_type( iterator_type const& src )
214                 : iterator_base( src )
215             {}
216
217             value_ptr operator ->() const
218             {
219                 typename iterator_base::value_ptr p = iterator_base::operator ->();
220                 return p ? &(p->m_Value) : nullptr;
221             }
222
223             value_ref operator *() const
224             {
225                 return (iterator_base::operator *()).m_Value;
226             }
227
228             /// Pre-increment
229             iterator_type& operator ++()
230             {
231                 iterator_base::operator ++();
232                 return *this;
233             }
234
235             template <bool C>
236             bool operator ==(iterator_type<C> const& i ) const
237             {
238                 return iterator_base::operator ==(i);
239             }
240             template <bool C>
241             bool operator !=(iterator_type<C> const& i ) const
242             {
243                 return iterator_base::operator !=(i);
244             }
245         };
246         //@endcond
247
248     public:
249     ///@name Forward iterators (only for debugging purpose)
250     //@{
251         /// Forward iterator
252         /**
253             You may safely use iterators in multi-threaded environment only under RCU lock.
254             Otherwise, a crash is possible if another thread deletes the item the iterator points to.
255         */
256         typedef iterator_type<false>    iterator;
257
258         /// Const forward iterator
259         /**
260             For iterator's features and requirements see \ref iterator
261         */
262         typedef iterator_type<true>     const_iterator;
263
264         /// Returns a forward iterator addressing the first element in a list
265         /**
266             For empty list \code begin() == end() \endcode
267         */
268         iterator begin()
269         {
270             iterator it( head());
271             ++it        ;   // skip dummy head node
272             return it;
273         }
274
275         /// Returns an iterator that addresses the location succeeding the last element in a list
276         /**
277             Do not use the value returned by <tt>end</tt> function to access any item.
278
279             The returned value can be used only to control reaching the end of the list.
280             For empty list \code begin() == end() \endcode
281         */
282         iterator end()
283         {
284             return iterator( tail());
285         }
286
287         /// Returns a forward const iterator addressing the first element in a list
288         const_iterator begin() const
289         {
290             const_iterator it( head());
291             ++it        ;   // skip dummy head node
292             return it;
293         }
294
295         /// Returns a forward const iterator addressing the first element in a list
296         const_iterator cbegin() const
297         {
298             const_iterator it( head());
299             ++it        ;   // skip dummy head node
300             return it;
301         }
302
303         /// Returns an const iterator that addresses the location succeeding the last element in a list
304         const_iterator end() const
305         {
306             return const_iterator( tail());
307         }
308
309         /// Returns an const iterator that addresses the location succeeding the last element in a list
310         const_iterator cend() const
311         {
312             return const_iterator( tail());
313         }
314     //@}
315
316     public:
317         /// Default constructor
318         LazyList()
319         {}
320
321         //@cond
322         template <typename Stat, typename = std::enable_if<std::is_same<stat, lazy_list::wrapped_stat<Stat>>::value >>
323         explicit LazyList( Stat& st )
324             : base_class( st )
325         {}
326         //@endcond
327
328         /// Desctructor clears the list
329         ~LazyList()
330         {
331             clear();
332         }
333
334         /// Inserts new node
335         /**
336             The function creates a node with copy of \p val value
337             and then inserts the node created into the list.
338
339             The type \p Q should contain as minimum the complete key of the node.
340             The object of \p value_type should be constructible from \p val of type \p Q.
341             In trivial case, \p Q is equal to \p value_type.
342
343             The function makes RCU lock internally.
344
345             Returns \p true if inserting successful, \p false otherwise.
346         */
347         template <typename Q>
348         bool insert( Q&& val )
349         {
350             return insert_at( head(), std::forward<Q>( val ));
351         }
352
353         /// Inserts new node
354         /**
355             This function inserts new node with default-constructed value and then it calls
356             \p func functor with signature
357             \code void func( value_type& itemValue ) ;\endcode
358
359             The argument \p itemValue of user-defined functor \p func is the reference
360             to the list's item inserted.
361             The user-defined functor is called only if the inserting is success.
362
363             The type \p Q should contain the complete key of the node.
364             The object of \ref value_type should be constructible from \p key of type \p Q.
365
366             The function allows to split creating of new item into two part:
367             - create item from \p key with initializing key-fields only;
368             - insert new item into the list;
369             - if inserting is successful, initialize non-key fields of item by calling \p f functor
370
371             This can be useful if complete initialization of object of \p value_type is heavyweight and
372             it is preferable that the initialization should be completed only if inserting is successful.
373
374             The function makes RCU lock internally.
375         */
376         template <typename Q, typename Func>
377         bool insert( Q&& key, Func func )
378         {
379             return insert_at( head(), std::forward<Q>( key ), func );
380         }
381
382         /// Inserts data of type \p value_type constructed from \p args
383         /**
384             Returns \p true if inserting successful, \p false otherwise.
385
386             The function makes RCU lock internally.
387         */
388         template <typename... Args>
389         bool emplace( Args&&... args )
390         {
391             return emplace_at( head(), std::forward<Args>(args)... );
392         }
393
394         /// Updates data by \p key
395         /**
396             The operation performs inserting or replacing the element with lock-free manner.
397
398             If the \p key not found in the list, then the new item created from \p key
399             will be inserted iff \p bAllowInsert is \p true.
400             Otherwise, if \p key is found, the functor \p func is called with item found.
401
402             The functor \p Func signature is:
403             \code
404                 struct my_functor {
405                     void operator()( bool bNew, value_type& item, Q const& val );
406                 };
407             \endcode
408
409             with arguments:
410             - \p bNew - \p true if the item has been inserted, \p false otherwise
411             - \p item - item of the list
412             - \p val - argument \p key passed into the \p %update() function
413
414             The functor may change non-key fields of the \p item;
415             during \p func call \p item is locked so it is safe to modify the item in
416             multi-threaded environment.
417
418             The function applies RCU lock internally.
419
420             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
421             \p second is true if new item has been added or \p false if the item with \p key
422             already exists.
423         */
424         template <typename Q, typename Func>
425         std::pair<bool, bool> update( Q const& key, Func func, bool bAllowInsert = true )
426         {
427             return update_at( head(), key, func, bAllowInsert );
428         }
429         //@cond
430         template <typename Q, typename Func>
431         CDS_DEPRECATED("ensure() is deprecated, use update()")
432         std::pair<bool, bool> ensure( Q const& key, Func f )
433         {
434             return update( key, f, true );
435         }
436         //@endcond
437
438         /// Deletes \p key from the list
439         /** \anchor cds_nonintrusive_LazyList_rcu_erase
440             Since the key of LazyList's item type \p T is not explicitly specified,
441             template parameter \p Q defines the key type searching in the list.
442             The list item comparator should be able to compare the type \p T of list item
443             and the type \p Q.
444
445             RCU \p synchronize method can be called. RCU should not be locked.
446
447             Return \p true if key is found and deleted, \p false otherwise
448         */
449         template <typename Q>
450         bool erase( Q const& key )
451         {
452             return erase_at( head(), key, intrusive_key_comparator(), [](value_type const&){} );
453         }
454
455         /// Deletes the item from the list using \p pred predicate for searching
456         /**
457             The function is an analog of \ref cds_nonintrusive_LazyList_rcu_erase "erase(Q const&)"
458             but \p pred is used for key comparing.
459             \p Less functor has the interface like \p std::less.
460             \p pred must imply the same element order as the comparator used for building the list.
461         */
462         template <typename Q, typename Less>
463         bool erase_with( Q const& key, Less pred )
464         {
465             CDS_UNUSED( pred );
466             return erase_at( head(), key, typename maker::template less_wrapper<Less>::type(), [](value_type const&){} );
467         }
468
469         /// Deletes \p key from the list
470         /** \anchor cds_nonintrusive_LazyList_rcu_erase_func
471             The function searches an item with key \p key, calls \p f functor
472             and deletes the item. If \p key is not found, the functor is not called.
473
474             The functor \p Func interface:
475             \code
476             struct extractor {
477                 void operator()(value_type const& val) { ... }
478             };
479             \endcode
480
481             Since the key of LazyList's item type \p T is not explicitly specified,
482             template parameter \p Q defines the key type searching in the list.
483             The list item comparator should be able to compare the type \p T of list item
484             and the type \p Q.
485
486             RCU \p synchronize method can be called. RCU should not be locked.
487
488             Return \p true if key is found and deleted, \p false otherwise
489         */
490         template <typename Q, typename Func>
491         bool erase( Q const& key, Func f )
492         {
493             return erase_at( head(), key, intrusive_key_comparator(), f );
494         }
495
496         /// Deletes the item from the list using \p pred predicate for searching
497         /**
498             The function is an analog of \ref cds_nonintrusive_LazyList_rcu_erase_func "erase(Q const&, Func)"
499             but \p pred is used for key comparing.
500             \p Less functor has the interface like \p std::less.
501             \p pred must imply the same element order as the comparator used for building the list.
502         */
503         template <typename Q, typename Less, typename Func>
504         bool erase_with( Q const& key, Less pred, Func f )
505         {
506             CDS_UNUSED( pred );
507             return erase_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
508         }
509
510         /// Extracts an item from the list
511         /**
512         @anchor cds_nonintrusive_LazyList_rcu_extract
513             The function searches an item with key equal to \p key in the list,
514             unlinks it from the list, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to an item found.
515             If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
516
517             @note The function does NOT call RCU read-side lock or synchronization,
518             and does NOT dispose the item found. It just excludes the item from the list
519             and returns a pointer to item found.
520             You should lock RCU before calling this function.
521
522             \code
523             #include <cds/urcu/general_buffered.h>
524             #include <cds/container/lazy_list_rcu.h>
525
526             typedef cds::urcu::gc< general_buffered<> > rcu;
527             typedef cds::container::LazyList< rcu, Foo > rcu_lazy_list;
528
529             rcu_lazy_list theList;
530             // ...
531
532             rcu_lazy_list::exempt_ptr p;
533             {
534                 // first, we should lock RCU
535                 rcu_lazy_list::rcu_lock sl;
536
537                 // Now, you can apply extract function
538                 // Note that you must not delete the item found inside the RCU lock
539                 p = theList.extract( 10 );
540                 if ( p ) {
541                     // do something with p
542                     ...
543                 }
544             }
545             // Outside RCU lock section we may safely release extracted pointer.
546             // release() passes the pointer to RCU reclamation cycle.
547             p.release();
548             \endcode
549         */
550         template <typename Q>
551         exempt_ptr extract( Q const& key )
552         {
553             return exempt_ptr(extract_at( head(), key, intrusive_key_comparator()));
554         }
555
556         /// Extracts an item from the list using \p pred predicate for searching
557         /**
558             This function is the analog for \p extract(Q const&).
559
560             The \p pred is a predicate used for key comparing.
561             \p Less has the interface like \p std::less.
562             \p pred must imply the same element order as \ref key_comparator.
563         */
564         template <typename Q, typename Less>
565         exempt_ptr extract_with( Q const& key, Less pred )
566         {
567             CDS_UNUSED( pred );
568             return exempt_ptr( extract_at( head(), key, typename maker::template less_wrapper<Less>::type()));
569         }
570
571         /// Checks whether the list contains \p key
572         /**
573             The function searches the item with key equal to \p key
574             and returns \p true if it is found, and \p false otherwise.
575
576             The function applies RCU lock internally.
577         */
578         template <typename Q>
579         bool contains( Q const& key ) const
580         {
581             return find_at( head(), key, intrusive_key_comparator());
582         }
583         //@cond
584         template <typename Q>
585         CDS_DEPRECATED("deprecated, use contains()")
586         bool find( Q const& key ) const
587         {
588             return contains( key );
589         }
590         //@endcond
591
592         /// Checks whether the list contains \p key using \p pred predicate for searching
593         /**
594             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
595             \p Less functor has the interface like \p std::less.
596             \p pred must imply the same element order as the comparator used for building the list.
597         */
598         template <typename Q, typename Less>
599         bool contains( Q const& key, Less pred ) const
600         {
601             CDS_UNUSED( pred );
602             return find_at( head(), key, typename maker::template less_wrapper<Less>::type());
603         }
604         //@cond
605         template <typename Q, typename Less>
606         CDS_DEPRECATED("deprecated, use contains()")
607         bool find_with( Q const& key, Less pred ) const
608         {
609             return contains( key, pred );
610         }
611         //@endcond
612
613         /// Finds the key \p key and performs an action with it
614         /** \anchor cds_nonintrusive_LazyList_rcu_find_func
615             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
616             The interface of \p Func functor is:
617             \code
618             struct functor {
619                 void operator()( value_type& item, Q& key );
620             };
621             \endcode
622             where \p item is the item found, \p key is the \p find() function argument.
623
624             The functor may change non-key fields of \p item. Note that the function is only guarantee
625             that \p item cannot be deleted during functor is executing.
626             The function does not serialize simultaneous access to the list \p item. If such access is
627             possible you must provide your own synchronization schema to exclude unsafe item modifications.
628
629             The \p key argument is non-const since it can be used as \p f functor destination i.e., the functor
630             may modify both arguments.
631
632             The function makes RCU lock internally.
633
634             The function returns \p true if \p key is found, \p false otherwise.
635         */
636         template <typename Q, typename Func>
637         bool find( Q& key, Func f ) const
638         {
639             return find_at( head(), key, intrusive_key_comparator(), f );
640         }
641         //@cond
642         template <typename Q, typename Func>
643         bool find( Q const& key, Func f ) const
644         {
645             return find_at( head(), key, intrusive_key_comparator(), f );
646         }
647         //@endcond
648
649         /// Finds the key \p key using \p pred predicate for searching
650         /**
651             The function is an analog of \ref cds_nonintrusive_LazyList_rcu_find_func "find(Q&, Func)"
652             but \p pred is used for key comparing.
653             \p Less functor has the interface like \p std::less.
654             \p pred must imply the same element order as the comparator used for building the list.
655         */
656         template <typename Q, typename Less, typename Func>
657         bool find_with( Q& key, Less pred, Func f ) const
658         {
659             CDS_UNUSED( pred );
660             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
661         }
662         //@cond
663         template <typename Q, typename Less, typename Func>
664         bool find_with( Q const& key, Less pred, Func f ) const
665         {
666             CDS_UNUSED( pred );
667             return find_at( head(), key, typename maker::template less_wrapper<Less>::type(), f );
668         }
669         //@endcond
670
671         /// Finds the key \p key and return the item found
672         /** \anchor cds_nonintrusive_LazyList_rcu_get
673             The function searches the item with key equal to \p key and returns the pointer to item found.
674             If \p key is not found it returns \p nullptr.
675
676             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
677
678             RCU should be locked before call of this function.
679             Returned item is valid only while RCU is locked:
680             \code
681             typedef cds::container::LazyList< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > ord_list;
682             ord_list theList;
683             // ...
684             {
685                 // Lock RCU
686                 ord_list::rcu_lock lock;
687
688                 foo * pVal = theList.get( 5 );
689                 if ( pVal ) {
690                     // Deal with pVal
691                     //...
692                 }
693                 // Unlock RCU by rcu_lock destructor
694                 // pVal can be freed at any time after RCU has been unlocked
695             }
696             \endcode
697         */
698         template <typename Q>
699         value_type * get( Q const& key ) const
700         {
701             return get_at( head(), key, intrusive_key_comparator());
702         }
703
704         /// Finds the key \p key and return the item found
705         /**
706             The function is an analog of \ref cds_nonintrusive_LazyList_rcu_get "get(Q const&)"
707             but \p pred is used for comparing the keys.
708
709             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
710             in any order.
711             \p pred must imply the same element order as the comparator used for building the list.
712         */
713         template <typename Q, typename Less>
714         value_type * get_with( Q const& key, Less pred ) const
715         {
716             CDS_UNUSED( pred );
717             return get_at( head(), key, typename maker::template less_wrapper<Less>::type());
718         }
719
720         /// Checks if the list is empty
721         bool empty() const
722         {
723             return base_class::empty();
724         }
725
726         /// Returns list's item count
727         /**
728             The value returned depends on \p Traits::item_counter type. For \p atomicity::empty_item_counter,
729             this function always returns 0.
730
731             @note Even if you use real item counter and it returns 0, this fact is not mean that the list
732             is empty. To check list emptyness use \ref empty() method.
733         */
734         size_t size() const
735         {
736             return base_class::size();
737         }
738
739         /// Returns const reference to internal statistics
740         stat const& statistics() const
741         {
742             return base_class::statistics();
743         }
744
745         /// Clears the list
746         void clear()
747         {
748             base_class::clear();
749         }
750
751     protected:
752         //@cond
753         bool insert_node( node_type * pNode )
754         {
755             return insert_node_at( head(), pNode );
756         }
757
758         bool insert_node_at( head_type& refHead, node_type * pNode )
759         {
760             assert( pNode != nullptr );
761             scoped_node_ptr p( pNode );
762
763             if ( base_class::insert_at( &refHead, *pNode )) {
764                 p.release();
765                 return true;
766             }
767
768             return false;
769         }
770
771         template <typename Q>
772         bool insert_at( head_type& refHead, Q&& val )
773         {
774             return insert_node_at( refHead, alloc_node( std::forward<Q>( val )));
775         }
776
777         template <typename... Args>
778         bool emplace_at( head_type& refHead, Args&&... args )
779         {
780             return insert_node_at( refHead, alloc_node( std::forward<Args>(args)... ));
781         }
782
783         template <typename Q, typename Func>
784         bool insert_at( head_type& refHead, Q&& key, Func f )
785         {
786             scoped_node_ptr pNode( alloc_node( std::forward<Q>( key )));
787
788             if ( base_class::insert_at( &refHead, *pNode, [&f](node_type& node){ f( node_to_value(node)); } )) {
789                 pNode.release();
790                 return true;
791             }
792             return false;
793         }
794
795         template <typename Q, typename Compare, typename Func>
796         bool erase_at( head_type& refHead, Q const& key, Compare cmp, Func f )
797         {
798             return base_class::erase_at( &refHead, key, cmp, [&f](node_type const& node){ f( node_to_value(node)); } );
799         }
800
801         template <typename Q, typename Compare>
802         node_type * extract_at( head_type& refHead, Q const& key, Compare cmp )
803         {
804             return base_class::extract_at( &refHead, key, cmp );
805         }
806
807         template <typename Q, typename Func>
808         std::pair<bool, bool> update_at( head_type& refHead, Q const& key, Func f, bool bAllowInsert )
809         {
810             scoped_node_ptr pNode( alloc_node( key ));
811
812             std::pair<bool, bool> ret = base_class::update_at( &refHead, *pNode,
813                 [&f, &key](bool bNew, node_type& node, node_type&){f( bNew, node_to_value(node), key );},
814                 bAllowInsert );
815             if ( ret.first && ret.second )
816                 pNode.release();
817
818             return ret;
819         }
820
821         template <typename Q, typename Compare>
822         bool find_at( head_type& refHead, Q const& key, Compare cmp ) const
823         {
824             return base_class::find_at( &refHead, key, cmp, [](node_type&, Q const&) {} );
825         }
826
827         template <typename Q, typename Compare, typename Func>
828         bool find_at( head_type& refHead, Q& val, Compare cmp, Func f ) const
829         {
830             return base_class::find_at( &refHead, val, cmp, [&f](node_type& node, Q& v){ f( node_to_value(node), v ); });
831         }
832
833         template <typename Q, typename Compare>
834         value_type * get_at( head_type& refHead, Q const& val, Compare cmp ) const
835         {
836             node_type * pNode = base_class::get_at( &refHead, val, cmp );
837             return pNode ? &pNode->m_Value : nullptr;
838         }
839
840         static value_type& node_to_value( node_type& n )
841         {
842             return n.m_Value;
843         }
844
845         static value_type const& node_to_value( node_type const& n )
846         {
847             return n.m_Value;
848         }
849
850         template <typename Q>
851         static node_type * alloc_node( Q&& v )
852         {
853             return cxx_allocator().New( std::forward<Q>( v ));
854         }
855
856         template <typename... Args>
857         static node_type * alloc_node( Args&&... args )
858         {
859             return cxx_allocator().MoveNew( std::forward<Args>( args )... );
860         }
861
862         static void free_node( node_type * pNode )
863         {
864             cxx_allocator().Delete( pNode );
865         }
866
867         head_type& head()
868         {
869             return base_class::m_Head;
870         }
871
872         head_type& head() const
873         {
874             return const_cast<head_type&>(base_class::m_Head);
875         }
876
877         head_type& tail()
878         {
879             return base_class::m_Tail;
880         }
881
882         head_type const&  tail() const
883         {
884             return base_class::m_Tail;
885         }
886         //@endcond
887     };
888
889 }} // namespace cds::container
890
891 #endif // #ifndef CDSLIB_CONTAINER_LAZY_LIST_RCU_H