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