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>
34 class 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");
147 InterruptibleBarrier &
148 InterruptibleBarrier::operator=(
const InterruptibleBarrier &b)
150 throw Exception(
"Barriers cannot be assigned");
158 InterruptibleBarrier &
159 InterruptibleBarrier::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;
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;
255 }
catch (Exception &e) {
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();
281 throw InterruptedException(
"InterruptibleBarrier forcefully interrupted, only "
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();