24 #include <core/threading/interruptible_barrier.h>
25 #include <core/threading/thread_list.h>
26 #include <core/exceptions/system.h>
27 #include <core/macros.h>
29 #include <core/threading/mutex.h>
30 #include <core/threading/wait_condition.h>
39 class InterruptibleBarrierData
42 unsigned int threads_left;
44 WaitCondition *waitcond;
47 InterruptibleBarrierData(Mutex *mutex)
53 this->mutex =
new Mutex();
56 waitcond =
new WaitCondition(this->mutex);
59 ~InterruptibleBarrierData()
61 if (own_mutex)
delete mutex;
90 InterruptibleBarrier::InterruptibleBarrier(
unsigned int count)
95 throw Exception(
"Barrier count must be at least 1");
97 __data =
new InterruptibleBarrierData(NULL);
98 __data->threads_left = 0;
101 __interrupted =
false;
119 throw Exception(
"Barrier count must be at least 1");
121 __data =
new InterruptibleBarrierData(mutex);
122 __data->threads_left = 0;
125 __interrupted =
false;
137 throw Exception(
"Barriers cannot be copied");
149 throw Exception(
"Barriers cannot be copied");
158 InterruptibleBarrier &
159 InterruptibleBarrier::operator=(
const InterruptibleBarrier &b)
161 throw Exception(
"Barriers cannot be assigned");
169 InterruptibleBarrier &
170 InterruptibleBarrier::operator=(
const InterruptibleBarrier *b)
172 throw Exception(
"Barriers cannot be assigned");
192 return __passed_threads;
205 if (likely(__data->own_mutex)) __data->mutex->lock();
206 __interrupted =
true;
207 __data->waitcond->wake_all();
208 if (likely(__data->own_mutex)) __data->mutex->unlock();
220 if (likely(__data->own_mutex)) __data->mutex->lock();
221 __interrupted =
false;
223 __data->threads_left =
_count;
224 __passed_threads.clear();
225 if (likely(__data->own_mutex)) __data->mutex->unlock();
245 if (likely(__data->own_mutex)) __data->mutex->lock();
247 if ( __data->threads_left == 0 ) {
249 __timeout = __interrupted = __wait_at_barrier =
false;
250 __data->threads_left =
_count;
251 __passed_threads->clear();
253 if ( __interrupted || __timeout ) {
255 if (likely(__data->own_mutex)) __data->mutex->unlock();
260 --__data->threads_left;
269 bool local_timeout =
false;
270 bool waker = (__data->threads_left == 0);
272 while ( __data->threads_left && !__interrupted && !__timeout && ! local_timeout) {
273 local_timeout = ! __data->waitcond->reltimed_wait(timeout_sec, timeout_nanosec);
275 if (local_timeout) __timeout =
true;
277 if ( __interrupted ) {
278 if (likely(__data->own_mutex)) __data->mutex->unlock();
280 "%u of %u threads reached the barrier",
284 if (waker || local_timeout) {
285 __wait_at_barrier = waker;
286 __data->waitcond->wake_all();
289 if (likely(__data->own_mutex)) __data->mutex->unlock();
291 if (__wait_at_barrier) {
unsigned int count()
Get number of threads this barrier will wait for.
void interrupt()
Interrupt the barrier.
virtual void wait()
Wait for other threads.
virtual void wait()
Wait for other threads.
virtual ~InterruptibleBarrier()
Destructor.
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
Base class for exceptions in Fawkes.
InterruptibleBarrier(unsigned int count)
Constructor.
unsigned int _count
Number of threads that are expected to wait for the barrier.
static Thread * current_thread()
Get the Thread instance of the currently running thread.
The current system call has been interrupted (for instance by a signal).
void print_trace()
Prints trace to stderr.
RefPtr< ThreadList > passed_threads()
Get a list of threads that passed the barrier.
RefPtr<> is a reference-counting shared smartpointer.
void reset()
Clears the barrier.
Mutex mutual exclusion lock.
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...