3 #ifndef CDSLIB_URCU_DISPOSE_THREAD_H
4 #define CDSLIB_URCU_DISPOSE_THREAD_H
9 #include <condition_variable>
10 #include <cds/details/aligned_type.h>
12 namespace cds { namespace urcu {
14 /// Reclamation thread for \p general_threaded and \p signal_threaded URCU
16 The object of this class contains a reclamation thread object and
17 necessary synchronization object(s). The object manages reclamation thread
18 and defines a set of messages (i.e. methods) to communicate with the thread.
20 Template argument \p Buffer defines the buffer type of \ref general_threaded (or \ref signal_threaded) URCU.
22 template <class Buffer>
26 typedef Buffer buffer_type ; ///< Buffer type
29 typedef std::thread thread_type;
30 typedef std::mutex mutex_type;
31 typedef std::condition_variable condvar_type;
32 typedef std::unique_lock< mutex_type > unique_lock;
34 class dispose_thread_starter: public thread_type
36 static void thread_func( dispose_thread * pThis )
42 dispose_thread_starter( dispose_thread * pThis )
43 : thread_type( thread_func, pThis )
47 typedef char thread_placeholder[ sizeof(dispose_thread_starter) ];
48 typename cds::details::aligned_type< thread_placeholder, alignof( dispose_thread_starter ) >::type m_threadPlaceholder;
49 dispose_thread_starter * m_DisposeThread;
51 // synchronization with disposing thread
53 condvar_type m_cvDataReady;
55 // Task for thread (dispose cycle)
56 buffer_type * volatile m_pBuffer;
57 uint64_t volatile m_nCurEpoch;
60 bool volatile m_bQuit;
62 // disposing pass sync
63 condvar_type m_cvReady;
64 bool volatile m_bReady;
67 private: // methods called from disposing thread
71 buffer_type * pBuffer;
75 epoch_retired_ptr rest;
79 unique_lock lock( m_Mutex );
81 // signal that we are ready to dispose
83 m_cvReady.notify_one();
85 // wait new data portion
87 m_cvDataReady.wait( lock );
90 m_bReady = false ; // we are busy
93 nCurEpoch = m_nCurEpoch;
99 assert( rest.m_nEpoch <= nCurEpoch );
104 rest = dispose_buffer( pBuffer, nCurEpoch );
108 epoch_retired_ptr dispose_buffer( buffer_type * pBuf, uint64_t nCurEpoch )
111 while ( pBuf->pop( p )) {
112 if ( p.m_nEpoch <= nCurEpoch ) {
116 if ( !pBuf->push( p ))
121 return epoch_retired_ptr();
128 : m_pBuffer( nullptr )
135 public: // methods called from any thread
136 /// Start reclamation thread
138 This function is called by \ref general_threaded object to start
139 internal reclamation thread.
143 m_DisposeThread = new (m_threadPlaceholder) dispose_thread_starter( this );
146 /// Stop reclamation thread
148 This function is called by \ref general_threaded object to
149 start reclamation cycle and then to terminate reclamation thread.
151 \p buf buffer contains retired objects ready to free.
153 void stop( buffer_type& buf, uint64_t nCurEpoch )
156 unique_lock lock( m_Mutex );
158 // wait while retiring pass done
160 m_cvReady.wait( lock );
162 // give a new work and set stop flag
164 m_nCurEpoch = nCurEpoch;
167 m_cvDataReady.notify_one();
169 m_DisposeThread->join();
172 /// Start reclamation cycle
174 This function is called by \ref general_threaded object
175 to notify the reclamation thread about a new work.
176 \p buf buffer contains retired objects ready to free.
177 The reclamation thread should free all \p buf objects
178 \p m_nEpoch field of which is no more than \p nCurEpoch.
180 If \p bSync parameter is \p true the calling thread should
181 wait until disposing done.
183 void dispose( buffer_type& buf, uint64_t nCurEpoch, bool bSync )
185 unique_lock lock( m_Mutex );
187 // wait while disposing pass done
189 m_cvReady.wait( lock );
195 m_nCurEpoch = nCurEpoch;
198 m_cvDataReady.notify_one();
202 m_cvReady.wait( lock );
206 }} // namespace cds::urcu
208 #endif // #ifdef CDSLIB_URCU_DISPOSE_THREAD_H