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