24 #include <baseapp/thread_manager.h> 25 #include <core/threading/thread.h> 26 #include <core/threading/mutex_locker.h> 27 #include <core/threading/wait_condition.h> 28 #include <core/threading/thread_initializer.h> 29 #include <core/threading/thread_finalizer.h> 30 #include <core/exceptions/software.h> 31 #include <core/exceptions/system.h> 33 #include <aspect/blocked_timing.h> 60 ThreadManager::ThreadManagerAspectCollector::ThreadManagerAspectCollector(ThreadManager *parent_manager)
62 __parent_manager = parent_manager;
67 ThreadManager::ThreadManagerAspectCollector::add(ThreadList &tl)
69 BlockedTimingAspect *timed_thread;
71 for (ThreadList::iterator i = tl.begin(); i != tl.end(); ++i) {
72 if ( (timed_thread = dynamic_cast<BlockedTimingAspect *>(*i)) != NULL ) {
73 throw IllegalArgumentException(
"ThreadProducerAspect may not add threads with BlockedTimingAspect");
77 __parent_manager->add_maybelocked(tl,
false);
82 ThreadManager::ThreadManagerAspectCollector::add(Thread *t)
84 BlockedTimingAspect *timed_thread;
86 if ( (timed_thread = dynamic_cast<BlockedTimingAspect *>(t)) != NULL ) {
87 throw IllegalArgumentException(
"ThreadProducerAspect may not add threads with BlockedTimingAspect");
90 __parent_manager->add_maybelocked(t,
false);
95 ThreadManager::ThreadManagerAspectCollector::remove(ThreadList &tl)
97 BlockedTimingAspect *timed_thread;
99 for (ThreadList::iterator i = tl.begin(); i != tl.end(); ++i) {
100 if ( (timed_thread = dynamic_cast<BlockedTimingAspect *>(*i)) != NULL ) {
101 throw IllegalArgumentException(
"ThreadProducerAspect may not remove threads with BlockedTimingAspect");
105 __parent_manager->remove_maybelocked(tl,
false);
110 ThreadManager::ThreadManagerAspectCollector::remove(Thread *t)
112 BlockedTimingAspect *timed_thread;
114 if ( (timed_thread = dynamic_cast<BlockedTimingAspect *>(t)) != NULL ) {
115 throw IllegalArgumentException(
"ThreadProducerAspect may not remove threads with BlockedTimingAspect");
118 __parent_manager->remove_maybelocked(t,
false);
125 throw AccessViolationException(
"ThreadManagerAspect threads may not force removal of threads");
129 ThreadManager::ThreadManagerAspectCollector::force_remove(
fawkes::Thread *t)
131 throw AccessViolationException(
"ThreadManagerAspect threads may not force removal of threads");
139 ThreadManager::ThreadManager()
141 __initializer = NULL;
145 __interrupt_timed_thread_wait =
false;
146 __aspect_collector =
new ThreadManagerAspectCollector(
this);
158 __initializer = NULL;
162 __interrupt_timed_thread_wait =
false;
163 __aspect_collector =
new ThreadManagerAspectCollector(
this);
164 set_inifin(initializer, finalizer);
169 ThreadManager::~ThreadManager()
173 for (__tit = __threads.begin(); __tit != __threads.end(); ++__tit) {
175 __tit->second.force_stop(__finalizer);
179 __untimed_threads.force_stop(__finalizer);
183 delete __waitcond_timedthreads;
184 delete __aspect_collector;
196 __initializer = initializer;
197 __finalizer = finalizer;
209 ThreadManager::internal_remove_thread(
Thread *t)
213 if ( (timed_thread = dynamic_cast<BlockedTimingAspect *>(t)) != NULL ) {
216 if ( __threads.find(hook) != __threads.end() ) {
217 __threads[hook].remove_locked(t);
218 if (__threads[hook].empty()) __threads.erase(hook);
221 __untimed_threads.remove_locked(t);
234 ThreadManager::internal_add_thread(Thread *t)
236 BlockedTimingAspect *timed_thread;
237 if ( (timed_thread = dynamic_cast<BlockedTimingAspect *>(t)) != NULL ) {
240 if ( __threads.find(hook) == __threads.end() ) {
241 __threads[hook].set_name(
"ThreadManagerList Hook %i", hook);
242 __threads[hook].set_maintain_barrier(
true);
244 __threads[hook].push_back_locked(t);
246 __waitcond_timedthreads->wake_all();
248 __untimed_threads.push_back_locked(t);
265 ThreadManager::add_maybelocked(ThreadList &tl,
bool lock)
267 if ( ! (__initializer && __finalizer) ) {
268 throw NullPointerException(
"ThreadManager: initializer/finalizer not set");
272 throw Exception(
"Not accepting new threads from list that is not fresh, " 273 "list '%s' already sealed", tl.name());
280 tl.init(__initializer, __finalizer);
281 }
catch (Exception &e) {
290 MutexLocker locker(__threads.mutex(), lock);
291 for (ThreadList::iterator i = tl.begin(); i != tl.end(); ++i) {
292 internal_add_thread(*i);
310 ThreadManager::add_maybelocked(Thread *thread,
bool lock)
312 if ( thread == NULL ) {
313 throw NullPointerException(
"FawkesThreadMananger: cannot add NULL as thread");
316 if ( ! (__initializer && __finalizer) ) {
317 throw NullPointerException(
"ThreadManager: initializer/finalizer not set");
321 __initializer->init(thread);
322 }
catch (CannotInitializeThreadException &e) {
323 thread->notify_of_failed_init();
324 e.append(
"Adding thread in ThreadManager failed");
333 }
catch (CannotInitializeThreadException &e) {
334 thread->notify_of_failed_init();
335 __finalizer->finalize(thread);
337 }
catch (Exception &e) {
338 thread->notify_of_failed_init();
339 CannotInitializeThreadException
340 cite(
"Could not initialize thread '%s'", thread->name());
342 __finalizer->finalize(thread);
344 }
catch (std::exception &e) {
345 thread->notify_of_failed_init();
346 CannotInitializeThreadException
347 cite(
"Could not initialize thread '%s'", thread->name());
348 cite.append(
"Caught std::exception or derivative: %s", e.what());
349 __finalizer->finalize(thread);
352 thread->notify_of_failed_init();
353 CannotInitializeThreadException
354 cite(
"Could not initialize thread '%s'", thread->name());
355 cite.append(
"Unknown exception caught");
356 __finalizer->finalize(thread);
361 MutexLocker locker(__threads.mutex(), lock);
362 internal_add_thread(thread);
381 ThreadManager::remove_maybelocked(ThreadList &tl,
bool lock)
383 if ( ! (__initializer && __finalizer) ) {
384 throw NullPointerException(
"ThreadManager: initializer/finalizer not set");
388 if ( ! tl.sealed() ) {
389 throw ThreadListNotSealedException(
"(ThreadManager) Cannot remove unsealed thread " 390 "list. Not accepting unsealed list '%s' for removal",
395 MutexLocker locker(__threads.mutex(), lock);
398 if ( ! tl.prepare_finalize(__finalizer) ) {
399 tl.cancel_finalize();
401 throw CannotFinalizeThreadException(
"One or more threads in list '%s' cannot be " 402 "finalized", tl.name());
404 }
catch (CannotFinalizeThreadException &e) {
407 }
catch (Exception &e) {
409 e.append(
"One or more threads in list '%s' cannot be finalized", tl.name());
410 throw CannotFinalizeThreadException(e);
415 tl.finalize(__finalizer);
416 }
catch (Exception &e) {
421 for (ThreadList::iterator i = tl.begin(); i != tl.end(); ++i) {
422 internal_remove_thread(*i);
442 ThreadManager::remove_maybelocked(Thread *thread,
bool lock)
444 if ( thread == NULL )
return;
446 if ( ! (__initializer && __finalizer) ) {
447 throw NullPointerException(
"ThreadManager: initializer/finalizer not set");
450 MutexLocker locker(__threads.mutex(), lock);
452 if ( ! thread->prepare_finalize() ) {
453 thread->cancel_finalize();
454 throw CannotFinalizeThreadException(
"Thread '%s'cannot be finalized", thread->name());
456 }
catch (CannotFinalizeThreadException &e) {
457 e.append(
"ThreadManager cannot stop thread '%s'", thread->name());
458 thread->cancel_finalize();
464 __finalizer->finalize(thread);
467 internal_remove_thread(thread);
498 __threads.mutex()->stopby();
499 bool caught_exception =
false;
500 Exception exc(
"Forced removal of thread list %s failed", tl.
name());
504 caught_exception =
true;
508 for (ThreadList::iterator i = tl.begin(); i != tl.end(); ++i) {
509 internal_remove_thread(*i);
514 if (caught_exception) {
548 if (__finalizer) __finalizer->finalize(thread);
551 internal_remove_thread(thread);
557 unsigned int timeout_usec)
561 unsigned int timeout_sec = 0;
562 if (timeout_usec >= 1000000) {
563 timeout_sec = timeout_usec / 1000000;
564 timeout_usec -= timeout_sec * 1000000;
568 if ( __threads.find(hook) != __threads.end() ) {
569 __threads[hook].wakeup_and_wait(timeout_sec, timeout_usec * 1000);
579 if ( __threads.find(hook) != __threads.end() ) {
581 __threads[hook].wakeup(barrier);
583 __threads[hook].wakeup();
585 if ( __threads[hook].size() == 0 ) {
586 __threads.erase(hook);
593 ThreadManager::try_recover(std::list<std::string> &recovered_threads)
596 for (__tit = __threads.begin(); __tit != __threads.end(); ++__tit) {
597 __tit->second.try_recover(recovered_threads);
604 ThreadManager::timed_threads_exist()
606 return (__threads.size() > 0);
611 ThreadManager::wait_for_timed_threads()
613 __interrupt_timed_thread_wait =
false;
614 __waitcond_timedthreads->wait();
615 if ( __interrupt_timed_thread_wait ) {
616 __interrupt_timed_thread_wait =
false;
622 ThreadManager::interrupt_timed_thread_wait()
624 __interrupt_timed_thread_wait =
true;
625 __waitcond_timedthreads->wake_all();
634 ThreadManager::aspect_collector()
const 636 return __aspect_collector;
bool sealed()
Check if list is sealed.
Wait until a given condition holds.
const char * name()
Name of the thread list.
virtual void lock() const
Lock list.
Fawkes library namespace.
void force_stop(ThreadFinalizer *finalizer)
Force stop of all threads.
Thread class encapsulation of pthreads.
void unlock()
Unlock the mutex.
Thread aspect to use blocked timing.
WakeupHook
Type to define at which hook the thread is woken up.
Base class for exceptions in Fawkes.
Thread initializer interface.
virtual void finalize()
Finalize the thread.
bool prepare_finalize()
Prepare finalization.
virtual void unlock() const
Unlock list.
The current system call has been interrupted (for instance by a signal).
void cancel()
Cancel a thread.
Thread list not sealed exception.
void join()
Join the thread.
WakeupHook blockedTimingAspectHook() const
Get the wakeup hook.
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
Thread finalizer interface.