Fixed memory leaks in threaded URCU (general_threaded, signal_threaded)
[libcds.git] / cds / urcu / general_buffered.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_URCU_GENERAL_BUFFERED_H
4 #define CDSLIB_URCU_GENERAL_BUFFERED_H
5
6 #include <cds/urcu/details/gpb.h>
7
8 namespace cds { namespace urcu {
9
10     /// User-space general-purpose RCU with deferred buffered reclamation
11     /** @anchor cds_urcu_general_buffered_gc
12
13         This is a wrapper around \p general_buffered class.
14
15         Template arguments:
16         - \p Buffer - lock-free queue or lock-free bounded queue.
17             Default is \p cds::container::VyukovMPMCCycleQueue< retired_ptr >
18         - \p Lock - mutex type, default is \p std::mutex
19         - \p Backoff - back-off schema, default is \p cds::backoff::Default
20     */
21     template <
22 #ifdef CDS_DOXGEN_INVOKED
23         class Buffer = cds::container::VyukovMPMCCycleQueue< retired_ptr >
24         ,class Lock = std::mutex
25         ,class Backoff = cds::backoff::Default
26 #else
27         class Buffer
28        ,class Lock
29        ,class Backoff
30 #endif
31     >
32     class gc< general_buffered< Buffer, Lock, Backoff > >: public details::gc_common
33     {
34     public:
35         typedef general_buffered< Buffer, Lock, Backoff >  rcu_implementation   ;    ///< Wrapped URCU implementation
36
37         typedef typename rcu_implementation::rcu_tag     rcu_tag     ;   ///< URCU tag
38         typedef typename rcu_implementation::thread_gc   thread_gc   ;   ///< Thread-side RCU part
39         typedef typename rcu_implementation::scoped_lock scoped_lock ;   ///< Access lock class
40
41         using details::gc_common::atomic_marked_ptr;
42
43     public:
44         /// Creates URCU \p %general_buffered singleton.
45         gc( size_t nBufferCapacity = 256 )
46         {
47             rcu_implementation::Construct( nBufferCapacity );
48         }
49
50         /// Destroys URCU \p %general_instant singleton
51         ~gc()
52         {
53             rcu_implementation::Destruct( true );
54         }
55
56     public:
57         /// Waits to finish a grace period and clears the buffer
58         /**
59             After grace period finished the function frees all retired pointer
60             from internal buffer.
61         */
62         static void synchronize()
63         {
64             rcu_implementation::instance()->synchronize();
65         }
66
67         /// Places retired pointer <\p p, \p pFunc> to internal buffer
68         /**
69             If the buffer is full, \ref synchronize function is invoked.
70         */
71         template <typename T>
72         static void retire_ptr( T * p, void (* pFunc)(T *) )
73         {
74             retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ) );
75             retire_ptr( rp );
76         }
77
78         /// Places retired pointer \p p with \p Disposer to internal buffer
79         /**
80             If the buffer is full, \ref synchronize function is invoked.
81         */
82         template <typename Disposer, typename T>
83         static void retire_ptr( T * p )
84         {
85             retire_ptr( p, cds::details::static_functor<Disposer, T>::call );
86         }
87
88         /// Places retired pointer \p p to internal buffer
89         /**
90             If the buffer is full, \ref synchronize function is invoked.
91         */
92         static void retire_ptr( retired_ptr& p )
93         {
94             rcu_implementation::instance()->retire_ptr(p);
95         }
96
97         /// Frees chain [ \p itFirst, \p itLast) in one synchronization cycle
98         template <typename ForwardIterator>
99         static void batch_retire( ForwardIterator itFirst, ForwardIterator itLast )
100         {
101             rcu_implementation::instance()->batch_retire( itFirst, itLast );
102         }
103
104         /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
105         template <typename Func>
106         static void batch_retire( Func e )
107         {
108             rcu_implementation::instance()->batch_retire( e );
109         }
110
111          /// Acquires access lock (so called RCU reader-side lock)
112         /**
113             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
114         */
115         static void access_lock()
116         {
117             thread_gc::access_lock();
118         }
119
120         /// Releases access lock (so called RCU reader-side lock)
121         /**
122             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
123         */
124         static void access_unlock()
125         {
126             thread_gc::access_unlock();
127         }
128
129         /// Returns the threshold of internal buffer
130         static size_t capacity()
131         {
132             return rcu_implementation::instance()->capacity();
133         }
134
135         /// Checks if the thread is inside read-side critical section (i.e. the lock is acquired)
136         /**
137             Usually, this function is used internally to be convinced
138             that subsequent remove action is not lead to a deadlock.
139         */
140         static bool is_locked()
141         {
142             return thread_gc::is_locked();
143         }
144
145         /// Forces retired object removal
146         /**
147             This function calls \ref synchronize
148         */
149         static void force_dispose()
150         {
151             synchronize();
152         }
153     };
154
155 }} // namespace cds::urcu
156
157 #endif // #ifndef CDSLIB_URCU_GENERAL_BUFFERED_H