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