24#include <core/exceptions/system.h>
25#include <core/macros.h>
26#include <core/threading/interruptible_barrier.h>
27#include <core/threading/mutex.h>
28#include <core/threading/thread_list.h>
29#include <core/threading/wait_condition.h>
34class InterruptibleBarrierData
37 unsigned int threads_left;
39 WaitCondition *waitcond;
42 InterruptibleBarrierData(Mutex *mutex)
48 this->mutex =
new Mutex();
51 waitcond =
new WaitCondition(this->mutex);
54 ~InterruptibleBarrierData()
88 throw Exception(
"Barrier count must be at least 1");
90 data_ =
new InterruptibleBarrierData(NULL);
91 data_->threads_left = 0;
96 num_threads_in_wait_function_ = 0;
111 throw Exception(
"Barrier count must be at least 1");
113 data_ =
new InterruptibleBarrierData(mutex);
114 data_->threads_left = 0;
117 interrupted_ =
false;
119 num_threads_in_wait_function_ = 0;
129 throw Exception(
"Barriers cannot be copied");
139 throw Exception(
"Barriers cannot be copied");
147InterruptibleBarrier &
148InterruptibleBarrier::operator=(
const InterruptibleBarrier &b)
150 throw Exception(
"Barriers cannot be assigned");
158InterruptibleBarrier &
159InterruptibleBarrier::operator=(
const InterruptibleBarrier *b)
161 throw Exception(
"Barriers cannot be assigned");
179 return passed_threads_;
191 if (likely(data_->own_mutex))
192 data_->mutex->lock();
194 data_->waitcond->wake_all();
195 if (likely(data_->own_mutex))
196 data_->mutex->unlock();
207 if (likely(data_->own_mutex))
208 data_->mutex->lock();
209 interrupted_ =
false;
211 data_->threads_left =
_count;
212 passed_threads_.clear();
213 if (likely(data_->own_mutex))
214 data_->mutex->unlock();
233 if (likely(data_->own_mutex))
234 data_->mutex->lock();
235 num_threads_in_wait_function_++;
237 if (data_->threads_left == 0) {
239 timeout_ = interrupted_ = wait_at_barrier_ =
false;
240 data_->threads_left =
_count;
241 passed_threads_->clear();
243 if (interrupted_ || timeout_) {
245 num_threads_in_wait_function_--;
246 if (likely(data_->own_mutex))
247 data_->mutex->unlock();
252 --data_->threads_left;
261 bool local_timeout =
false;
264 bool waker = (data_->threads_left == 0);
266 while (data_->threads_left && !interrupted_ && !timeout_ && !local_timeout) {
269 local_timeout = !data_->waitcond->reltimed_wait(timeout_sec, timeout_nanosec);
279 if (likely(data_->own_mutex))
280 data_->mutex->unlock();
282 "%u of %u threads reached the barrier",
283 _count - data_->threads_left,
289 wait_at_barrier_ =
true;
292 if (waker || local_timeout) {
294 data_->waitcond->wake_all();
297 if (likely(data_->own_mutex))
298 data_->mutex->unlock();
300 if (wait_at_barrier_) {
305 if (likely(data_->own_mutex))
306 data_->mutex->lock();
308 num_threads_in_wait_function_--;
309 if (likely(data_->own_mutex))
310 data_->mutex->unlock();
323 if (likely(data_->own_mutex))
324 data_->mutex->lock();
325 bool res = num_threads_in_wait_function_ == 0;
326 if (likely(data_->own_mutex))
327 data_->mutex->unlock();
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
unsigned int _count
Number of threads that are expected to wait for the barrier.
virtual void wait()
Wait for other threads.
unsigned int count()
Get number of threads this barrier will wait for.
Base class for exceptions in Fawkes.
void print_trace() noexcept
Prints trace to stderr.
The current system call has been interrupted (for instance by a signal).
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
void interrupt() noexcept
Interrupt the barrier.
virtual void wait()
Wait for other threads.
InterruptibleBarrier(unsigned int count)
Constructor.
void reset() noexcept
Clears the barrier.
virtual ~InterruptibleBarrier()
Destructor.
bool no_threads_in_wait()
Checks if there are no more threads in the wait() function.
RefPtr< ThreadList > passed_threads()
Get a list of threads that passed the barrier.
Mutex mutual exclusion lock.
RefPtr<> is a reference-counting shared smartpointer.
static Thread * current_thread()
Get the Thread instance of the currently running thread.
Fawkes library namespace.