24#include <core/exceptions/software.h>
25#include <core/exceptions/system.h>
26#include <core/threading/barrier.h>
27#include <core/threading/interruptible_barrier.h>
28#include <core/threading/mutex.h>
29#include <core/threading/mutex_locker.h>
30#include <core/threading/thread.h>
31#include <core/threading/thread_list.h>
56 append(
"Operation '%s' is not allowed on a sealed thread list", operation);
94 name_ = strdup(tlname);
96 finalize_mutex_ =
new Mutex();
109 name_ = strdup(tlname);
111 finalize_mutex_ =
new Mutex();
114 if (maintain_barrier)
123 name_ = strdup(tl.name_);
124 sealed_ = tl.sealed_;
125 finalize_mutex_ =
new Mutex();
127 if (tl.wnw_barrier_ != NULL)
135 delete finalize_mutex_;
147 name_ = strdup(tl.name_);
148 sealed_ = tl.sealed_;
149 finalize_mutex_ =
new Mutex();
151 if (tl.wnw_barrier_ != NULL)
163 for (iterator i = begin(); i != end(); ++i) {
175 for (iterator i = begin(); i != end(); ++i) {
188 for (iterator i = begin(); i != end(); ++i) {
189 (*i)->wakeup(barrier);
202 unsigned int count = 1;
203 for (iterator i = begin(); i != end(); ++i) {
204 if (!(*i)->flagged_bad()) {
206 (*i)->wakeup(barrier);
222 if (count != barrier->
count()) {
223 throw Exception(
"ThreadList(%s)::wakeup(): barrier has count (%u) different "
224 "from number of unflagged threads (%u)",
245 "barrier is maintained");
255 if (!wnw_barrier_->
wait(timeout_sec, timeout_nanosec)) {
259 for (iterator i = begin(); i != end(); ++i) {
260 if ((*i)->flagged_bad()) {
265 for (iterator j = passed_threads->begin(); j != passed_threads->end(); ++j) {
277 wnw_bad_barriers_.push_back(make_pair(wnw_barrier_, bad_threads));
284 if (bad_threads.size() > 1) {
285 s =
"Multiple threads did not finish in time, flagging as bad: ";
286 for (iterator i = bad_threads.begin(); i != bad_threads.end(); ++i) {
287 s += std::string((*i)->name()) +
" ";
289 }
else if (bad_threads.size() == 0) {
290 s =
"Timeout happened, but no bad threads recorded.";
292 throw Exception(
"Thread %s did not finish in time (max %f), flagging as bad",
293 bad_threads.front()->
name(),
294 (
float)timeout_sec + (
float)timeout_nanosec / 1000000000.);
310 throw Exception(
"InterruptibleBarrier cannot be destroyed "
311 "when there still are threads in the wait() function");
315 if (maintain_barrier)
331 bool changed =
false;
332 wnw_bbit_ = wnw_bad_barriers_.begin();
333 while (wnw_bbit_ != wnw_bad_barriers_.end()) {
334 iterator i = wnw_bbit_->second.begin();
335 while (i != wnw_bbit_->second.end()) {
336 if ((*i)->cancelled()) {
338 i = wnw_bbit_->second.erase(i);
340 }
else if ((*i)->waiting()) {
342 recovered_threads.push_back((*i)->name());
345 i = wnw_bbit_->second.erase(i);
351 if (wnw_bbit_->second.empty() && wnw_bbit_->first->no_threads_in_wait()) {
352 delete wnw_bbit_->first;
353 wnw_bbit_ = wnw_bad_barriers_.erase(wnw_bbit_);
379 for (ThreadList::iterator i = begin(); i != end(); ++i) {
381#ifndef DEBUG_THREAD_INIT
384 initializer->
init(*i);
385#ifndef DEBUG_THREAD_INIT
387 cite.
append(
"Initialized failed to initialize thread '%s'", (*i)->name());
396#ifndef DEBUG_THREAD_INIT
401#ifndef DEBUG_THREAD_INIT
403 notify_of_failed_init();
404 cite.
append(
"Initializing thread '%s' in list '%s' failed", (*i)->name(), name_);
410 notify_of_failed_init();
412 cite.
append(
"Could not initialize thread '%s' (ThreadList %s)", (*i)->name(),
name());
416 }
catch (std::exception &e) {
417 notify_of_failed_init();
418 cite.
append(
"Caught std::exception: %s", e.
what());
419 cite.
append(
"Could not initialize thread '%s' (ThreadList %s)", (*i)->name(),
name());
424 notify_of_failed_init();
425 cite.
append(
"Could not initialize thread '%s' (ThreadList %s)", (*i)->name(),
name());
426 cite.
append(
"Unknown exception caught");
435 initialized_threads.
finalize(finalizer);
449 for (iterator i = begin(); i != end(); ++i) {
474 for (iterator i = begin(); i != end(); ++i) {
499 for (iterator i = begin(); i != end(); ++i) {
513 for (reverse_iterator i = rbegin(); i != rend(); ++i) {
536 bool can_finalize =
true;
538 bool threw_exception =
false;
539 for (reverse_iterator i = rbegin(); i != rend(); ++i) {
545 can_finalize =
false;
547 if (!(*i)->prepare_finalize()) {
548 can_finalize =
false;
551 cfte.
append(
"Thread '%s' threw an exception while preparing finalization of "
552 "ThreadList '%s' (IGNORED)",
556 threw_exception =
true;
558 cfte.
append(
"Thread '%s' threw a generic exception while preparing finalization of "
559 "ThreadList '%s' (IGNORED)",
563 threw_exception =
true;
566 if (threw_exception) {
583 Exception me(
"One or more threads failed to finalize");
584 for (reverse_iterator i = rbegin(); i != rend(); ++i) {
589 me.
append(
"AspectIniFin called Thread[%s]::finalize() which failed", (*i)->name());
593 me.
append(
"AspectIniFin called Thread[%s]::finalize() which failed", (*i)->name());
597 me.
append(
"Thread[%s]::finalize() threw unsupported exception", (*i)->name());
603 me.
append(
"Could not finalize thread '%s' in list '%s'", (*i)->name(), name_);
619 for (reverse_iterator i = rbegin(); i != rend(); ++i) {
620 (*i)->cancel_finalize();
636 for (i = begin(); i != end(); ++i) {
637 (*i)->set_prepfin_hold(hold);
642 for (iterator j = begin(); j != i; ++j) {
643 (*j)->set_prepfin_hold(
false);
657 bool caught_exception =
false;
658 Exception exc(
"Forced thread finalization failed");
663 caught_exception =
true;
669 caught_exception =
true;
675 caught_exception =
true;
679 if (caught_exception) {
703 va_start(va, format);
706 if (vasprintf(&tmpname, format, va) != -1) {
888ThreadList::update_barrier()
890 unsigned int num = 1;
891 for (iterator i = begin(); i != end(); ++i) {
892 if (!(*i)->flagged_bad())
900 wnw_bad_barriers_.push_back(make_pair(wnw_barrier_, empty_list));
902 wnw_barrier_ =
new InterruptibleBarrier(num);
907ThreadList::notify_of_failed_init()
909 for (ThreadList::iterator i = begin(); i != end(); ++i) {
910 (*i)->notify_of_failed_init();
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
unsigned int count()
Get number of threads this barrier will wait for.
Thread cannot be finalized.
Thread cannot be initialized.
Base class for exceptions in Fawkes.
virtual const char * what() const noexcept
Get primary string.
void append_va(const char *format, va_list va) noexcept
Append messages to the message list.
void append(const char *format,...) noexcept
Append messages to the message list.
bool wait(unsigned int timeout_sec, unsigned int timeout_nanosec)
Wait for other threads.
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.
LockList< Type > & operator=(const LockList< Type > &ll)
Copy values from another LockList.
virtual void lock() const
Lock list.
RefPtr< Mutex > mutex() const
Get access to the internal mutex.
Mutex mutual exclusion lock.
A NULL pointer was supplied where not allowed.
System ran out of memory and desired operation could not be fulfilled.
RefPtr<> is a reference-counting shared smartpointer.
Thread finalizer interface.
virtual bool prepare_finalize(Thread *thread)=0
Prepare finalization of a thread.
virtual void finalize(Thread *thread)=0
Finalize a thread.
Thread initializer interface.
virtual void init(Thread *thread)=0
This method is called by the ThreadManager for each newly added Thread.
ThreadListNotSealedException(const char *format,...)
Constructor.
Thread list sealed exception.
ThreadListSealedException(const char *operation)
Constructor.
void wakeup_unlocked()
Wakeup all threads in list.
void remove_locked(Thread *thread)
Remove with lock protection.
ThreadList::iterator erase(iterator pos)
Erase element at given position.
void push_front_locked(Thread *thread)
Add thread to the front with lock protection.
void clear()
Clear the list.
bool prepare_finalize(ThreadFinalizer *finalizer)
Prepare finalize.
void set_prepfin_hold(bool hold)
Set prepfin hold on all threads.
void init(ThreadInitializer *initializer, ThreadFinalizer *finalizer)
Initialize threads.
ThreadList & operator=(const ThreadList &tl)
Assignment operator.
void finalize(ThreadFinalizer *finalizer)
Finalize Threads.
void set_name(const char *format,...)
Set name of thread.
void cancel()
Cancel threads.
void wakeup()
Wakeup all threads in list.
void pop_front()
Remove first element.
void try_recover(std::list< std::string > &recovered_threads)
Check if any of the bad barriers recovered.
void push_back_locked(Thread *thread)
Add thread to the end with lock protection.
void remove(Thread *thread)
Remove with lock protection.
const char * name()
Name of the thread list.
void force_stop(ThreadFinalizer *finalizer)
Force stop of all threads.
void cancel_finalize()
Cancel finalization on all threads.
void pop_back()
Remove last element.
void push_front(Thread *thread)
Add thread to the front.
ThreadList(const char *tlname="")
Constructor.
void set_maintain_barrier(bool maintain_barrier)
Set if this thread list should maintain a barrier.
bool sealed()
Check if list is sealed.
void start()
Start threads.
void seal()
Seal the list.
void wakeup_and_wait(unsigned int timeout_sec=0, unsigned int timeout_nanosec=0)
Wakeup threads and wait for them to finish.
void push_back(Thread *thread)
Add thread to the end.
Thread class encapsulation of pthreads.
static const unsigned int FLAG_BAD
Standard thread flag: "thread is bad".
Fawkes library namespace.