Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
thread_list.cpp
1 
2 /***************************************************************************
3  * thread_list.cpp - Thread list
4  *
5  * Created: Tue Oct 31 18:20:59 2006
6  * Copyright 2006-2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <core/threading/thread_list.h>
25 #include <core/threading/thread.h>
26 #include <core/threading/mutex.h>
27 #include <core/threading/mutex_locker.h>
28 #include <core/threading/barrier.h>
29 #include <core/threading/interruptible_barrier.h>
30 #include <core/exceptions/software.h>
31 #include <core/exceptions/system.h>
32 
33 #include <string>
34 #include <cstring>
35 #include <cstdlib>
36 #include <cstdio>
37 #include <unistd.h>
38 
39 namespace fawkes {
40 
41 /** @class ThreadListSealedException <core/threading/thread_list.h>
42  * Thread list sealed exception.
43  * This exception is thrown whenever you execute an action that would
44  * modify the thread list like adding or removing elements on a
45  * sealed list. A list can only be sealed and never be unsealed afterwards.
46  * This exception is meant to be only thrown by ThreadList.
47  * @author Tim Niemueller
48  */
49 
50 /** Constructor.
51  * @param operation operation that failed
52  */
54  : Exception("ThreadList is sealed")
55 {
56  append("Operation '%s' is not allowed on a sealed thread list", operation);
57 }
58 
59 
60 /** @class ThreadListNotSealedException <core/threading/thread_list.h>
61  * Thread list not sealed exception.
62  * This exception is thrown whenever the thread list is given to some
63  * method that expects a sealed list (probably because it sealed the
64  * list by itself).
65  * This exception is meant to be only thrown by users of ThreadList.
66  * @author Tim Niemueller
67  */
68 
69 /** Constructor.
70  * @param format format of message
71  */
73  : Exception()
74 {
75  va_list va;
76  va_start(va, format);
77  append_va(format, va);
78  va_end(va);
79 }
80 
81 /** @class ThreadList <core/threading/thread_list.h>
82  * List of threads.
83  * This is a list of threads derived from stl::list. It features special
84  * wakeup methods that will wakeup all threads in the list. The list can
85  * and must be locked in iterator operations and when adding or deleting
86  * elements from the list.
87  * @author Tim Niemueller
88  */
89 
90 /** Constructor.
91  * @param tlname optional name which is used for better readable error
92  * messages.
93  */
94 ThreadList::ThreadList(const char *tlname)
95 {
96  __name = strdup(tlname);
97  __sealed = false;
98  __finalize_mutex = new Mutex();
99  __wnw_barrier = NULL;
100  clear();
101 }
102 
103 
104 /** Constructor.
105  * @param maintain_barrier if true, an internal barrier is maintained during add and
106  * remove operations such that wakeup_and_wait() can be used.
107  * @param tlname optional name which is used for better readable error
108  * messages.
109  */
110 ThreadList::ThreadList(bool maintain_barrier, const char *tlname)
111 {
112  __name = strdup(tlname);
113  __sealed = false;
114  __finalize_mutex = new Mutex();
115  __wnw_barrier = NULL;
116  clear();
117  if ( maintain_barrier) update_barrier();
118 }
119 
120 
121 /** Copy constructor.
122  * @param tl thread list to copy
123  */
125  : LockList<Thread *>(tl)
126 {
127  __name = strdup(tl.__name);
128  __sealed = tl.__sealed;
129  __finalize_mutex = new Mutex();
130  __wnw_barrier = NULL;
131  if ( tl.__wnw_barrier != NULL ) update_barrier();
132 }
133 
134 
135 /** Destructor. */
137 {
138  free(__name);
139  delete __finalize_mutex;
140  delete __wnw_barrier;
141 }
142 
143 
144 /** Assignment operator.
145  * @param tl thread list to assign
146  * @return reference to this instance
147  */
148 ThreadList &
150 {
152  __name = strdup(tl.__name);
153  __sealed = tl.__sealed;
154  __finalize_mutex = new Mutex();
155  __wnw_barrier = NULL;
156  if ( tl.__wnw_barrier != NULL ) update_barrier();
157 
158  return *this;
159 }
160 
161 
162 /** Wakeup all threads in list. */
163 void
165 {
167 
168  for (iterator i = begin(); i != end(); ++i) {
169  (*i)->wakeup();
170  }
171 }
172 
173 
174 /** Wakeup all threads in list.
175  * This method wakes up all thread without acquiring the lock first.
176  * This method must only be used if the thread list is locked otherwise!
177  */
178 void
180 {
181  for (iterator i = begin(); i != end(); ++i) {
182  (*i)->wakeup();
183  }
184 }
185 
186 
187 /** Wakeup all threads in list and have them wait for the barrier.
188  * @param barrier Barrier to wait for after loop
189  */
190 void
192 {
194 
195  for (iterator i = begin(); i != end(); ++i) {
196  (*i)->wakeup(barrier);
197  }
198 }
199 
200 
201 /** Wakeup all threads in list and have them wait for the barrier.
202  * This method wakes up all thread without aquiring the lock first.
203  * This method must only be used if the thread list is locked otherwise!
204  * @param barrier Barrier to wait for after loop
205  */
206 void
208 {
209  Exception *exc = NULL;
210  unsigned int count = 1;
211  for (iterator i = begin(); i != end(); ++i) {
212  if ( ! (*i)->flagged_bad() ) {
213  try {
214  (*i)->wakeup(barrier);
215  } catch (Exception &e) {
216  if (! exc) {
217  exc = new Exception(e);
218  } else {
219  exc->append(e);
220  }
221  }
222  ++count;
223  }
224  }
225  if (exc) {
226  Exception te(*exc);
227  delete exc;
228  throw te;
229  }
230  if (count != barrier->count()) {
231  throw Exception("ThreadList(%s)::wakeup(): barrier has count (%u) different "
232  "from number of unflagged threads (%u)", __name, barrier->count(), count);
233  }
234 }
235 
236 
237 /** Wakeup threads and wait for them to finish.
238  * This assumes that all threads are in wait-for-wakeup mode. The threads are woken
239  * up with an internally maintained barrier. The method will return when all threads
240  * have finished one loop() iteration.
241  * @param timeout_sec timeout in seconds
242  * @param timeout_nanosec timeout in nanoseconds
243  * @exception NullPointerException thrown, if no internal barrier is maintained. Make sure
244  * you use the proper constructor.
245  */
246 void
247 ThreadList::wakeup_and_wait(unsigned int timeout_sec, unsigned int timeout_nanosec)
248 {
249  if ( ! __wnw_barrier ) {
250  throw NullPointerException("ThreadList::wakeup_and_wait() can only be called if "
251  "barrier is maintained");
252  }
253 
255 
256  try {
257  wakeup_unlocked(__wnw_barrier);
258  } catch (Exception &e) {
259  throw;
260  }
261  if ( ! __wnw_barrier->wait(timeout_sec, timeout_nanosec) ) {
262  // timeout, we have a bad thread, flag it
263  RefPtr<ThreadList> passed_threads = __wnw_barrier->passed_threads();
264  ThreadList bad_threads;
265  for (iterator i = begin(); i != end(); ++i) {
266  bool ok = false;
267  for (iterator j = passed_threads->begin(); j != passed_threads->end(); ++j) {
268  if (*j == *i) {
269  ok = true;
270  break;
271  }
272  }
273  if (! ok) {
274  bad_threads.push_back(*i);
275  (*i)->set_flag(Thread::FLAG_BAD);
276  }
277  }
278 
279  __wnw_bad_barriers.push_back(make_pair(__wnw_barrier, bad_threads));
280 
281  __wnw_barrier = NULL;
282  update_barrier();
283 
284  // Formulate exception
285  std::string s;
286  if ( bad_threads.size() > 1 ) {
287  s = "Multiple threads did not finish in time, flagging as bad: ";
288  for (iterator i = bad_threads.begin(); i != bad_threads.end(); ++i) {
289  s += std::string((*i)->name()) + " ";
290  }
291  } else if (bad_threads.size() == 0) {
292  s = "Timeout happened, but no bad threads recorded.";
293  } else {
294  throw Exception("Thread %s did not finish in time (max %f), flagging as bad",
295  bad_threads.front()->name(),
296  (float)timeout_sec + (float)timeout_nanosec / 1000000000.);
297  }
298  throw Exception("%s", s.c_str());
299  }
300 }
301 
302 
303 /** Set if this thread list should maintain a barrier.
304  * This operation does an implicit locking of the list.
305  * @param maintain_barrier true to maintain an internal barrier, false to disable it.
306  */
307 void
308 ThreadList::set_maintain_barrier(bool maintain_barrier)
309 {
311 
312  delete __wnw_barrier;
313  __wnw_barrier = NULL;
314  if ( maintain_barrier ) update_barrier();
315 }
316 
317 
318 /** Check if any of the bad barriers recovered.
319  * If the ThreadList maintains the barrier these may get bad if a thread does
320  * not finish in time. This method will check all bad barriers if the bad threads
321  * have recovered, and if so it will re-integrate the bad threads.
322  * @param recovered_threads upon return the names of any threads that could be
323  * recovered from a bad state have been added to the list.
324  */
325 void
326 ThreadList::try_recover(std::list<std::string> &recovered_threads)
327 {
329 
330  bool changed = false;
331  __wnw_bbit = __wnw_bad_barriers.begin();
332  while (__wnw_bbit != __wnw_bad_barriers.end()) {
333  iterator i = __wnw_bbit->second.begin();
334  while (i != __wnw_bbit->second.end()) {
335  if ( (*i)->waiting() ) {
336  // waiting means running() finished and the barrier has been passed
337  recovered_threads.push_back((*i)->name());
338  // it finally finished, re-integrate and hope that it does not bust again
339  (*i)->unset_flag(Thread::FLAG_BAD);
340  i = __wnw_bbit->second.erase(i);
341  changed = true;
342  } else {
343  ++i;
344  }
345  }
346  if ( __wnw_bbit->second.empty() ) {
347  delete __wnw_bbit->first;
348  __wnw_bbit = __wnw_bad_barriers.erase(__wnw_bbit);
349  } else {
350  ++__wnw_bbit;
351  }
352  }
353  if ( changed ) update_barrier();
354 }
355 
356 /** Initialize threads.
357  * The threads are being initialized.
358  * This operation is carried out unlocked. Lock it from the outside if needed.
359  * This is done because it is likely that this will be chained with other
360  * actions that require locking, thus you can lock the whole operation.
361  * @param initializer thread initializer to use
362  * @param finalizer finalizer to use to finalize threads that have been successfully
363  * initialized before one thread failed.
364  * @exception CannotInitializeThreadException thrown if at least one of the
365  * threads in this list could not be initialized.
366  */
367 void
369 {
371  ThreadList initialized_threads;
372  bool success = true;
373  for (ThreadList::iterator i = begin(); i != end(); ++i) {
374  // if initializer fails, we assume it handles finalization
375  try {
376  initializer->init(*i);
377  } catch (Exception &e) {
378  cite.append("Initialized failed to initialize thread '%s'", (*i)->name());
379  cite.append(e);
380  success = false;
381  break;
382  }
383  // if the thread's init() method fails, we need to finalize that very
384  // thread only with the finalizer, already initialized threads muts be
385  // fully finalized
386  try {
387  (*i)->init();
388  initialized_threads.push_back(*i);
389  } catch (CannotInitializeThreadException &e) {
390  notify_of_failed_init();
391  cite.append("Initializing thread '%s' in list '%s' failed",
392  (*i)->name(), __name);
393  cite.append(e);
394  finalizer->finalize(*i);
395  success = false;
396  break;
397  } catch (Exception &e) {
398  notify_of_failed_init();
399  cite.append("Could not initialize thread '%s'", (*i)->name());
400  cite.append(e);
401  finalizer->finalize(*i);
402  success = false;
403  break;
404  } catch (std::exception &e) {
405  notify_of_failed_init();
406  cite.append("Could not initialize thread '%s'", (*i)->name());
407  cite.append("Caught std::exception or derivative: %s", e.what());
408  finalizer->finalize(*i);
409  success = false;
410  break;
411  } catch (...) {
412  notify_of_failed_init();
413  cite.append("Could not initialize thread '%s'", (*i)->name());
414  cite.append("Unknown exception caught");
415  finalizer->finalize(*i);
416  success = false;
417  break;
418  }
419  }
420 
421  if ( ! success ) {
422  initialized_threads.finalize(finalizer);
423  throw cite;
424  }
425 }
426 
427 
428 /** Start threads.
429  * The threads are started.
430  * This operation is carried out unlocked. Lock it from the outside if needed.
431  * This is done because it is likely that this will be chained with other
432  * actions that require locking, thus you can lock the whole operation.
433  */
434 void
436 {
437  for (iterator i = begin(); i != end(); ++i) {
438  (*i)->start();
439  }
440 }
441 
442 
443 /** Cancel threads.
444  * The threads are canceled.
445  * This operation is carried out unlocked. Lock it from the outside if needed.
446  * This is done because it is likely that this will be chained with other
447  * actions that require locking, thus you can lock the whole operation.
448  *
449  * This is especially handy for detached threads. Since errorneous behavior
450  * has been seen when run inside gdb something like
451  * @code
452  * tl.cancel();
453  * tl.join();
454  * @endcode
455  * shout be avoided. Instead use
456  * @code
457  * tl.stop();
458  * @endcode
459  */
460 void
462 {
463  for (iterator i = begin(); i != end(); ++i) {
464  (*i)->cancel();
465  }
466 }
467 
468 
469 /** Join threads.
470  * The threads are joined.
471  * This operation is carried out unlocked. Lock it from the outside if needed.
472  * This is done because it is likely that this will be chained with other
473  * actions that require locking, thus you can lock the whole operation.
474  *
475  * Since errorneous behavior
476  * has been seen when run inside gdb something like
477  * @code
478  * tl.cancel();
479  * tl.join();
480  * @endcode
481  * shout be avoided. Instead use
482  * @code
483  * tl.stop();
484  * @endcode
485  */
486 void
488 {
489  for (iterator i = begin(); i != end(); ++i) {
490  (*i)->join();
491  }
492 }
493 
494 
495 /** Stop threads.
496  * The threads are canceled and joined.
497  * This operation is carried out unlocked. Lock it from the outside if needed.
498  * This is done because it is likely that this will be chained with other
499  * actions that require locking, thus you can lock the whole operation.
500  */
501 void
503 {
504  for (reverse_iterator i = rbegin(); i != rend(); ++i) {
505  (*i)->cancel();
506  (*i)->join();
507  // Workaround for pthreads annoyance
508  usleep(5000);
509  }
510 }
511 
512 
513 /** Prepare finalize.
514  * The threads are prepared for finalization. If any of the threads return
515  * false the whole list will return false.
516  * This operation is carried out unlocked. Lock it from the outside if needed.
517  * This is done because it is likely that this will be chained with other
518  * actions that require locking, thus you can lock the whole operation.
519  * @param finalizer thread finalizer to use to prepare finalization of the threads
520  * @return true, if prepare_finalize() returned true for all threads in the
521  * list, false if at least one thread returned false.
522  */
523 bool
525 {
526  MutexLocker lock(__finalize_mutex);
527 
528  bool can_finalize = true;
529  CannotFinalizeThreadException cfte("Cannot finalize one or more threads");
530  bool threw_exception = false;
531  for (reverse_iterator i = rbegin(); i != rend(); ++i) {
532  // Note that this loop may NOT be interrupted in the middle by break,
533  // since even if the thread denies finalization it can still be finalized
534  // and we have to ensure that every thread got a call to prepare_finalize()!
535  try {
536  if ( ! finalizer->prepare_finalize(*i) ) {
537  can_finalize = false;
538  }
539  if ( ! (*i)->prepare_finalize() ) {
540  can_finalize = false;
541  }
542  } catch (CannotFinalizeThreadException &e) {
543  cfte.append("Thread '%s' throw an exception while preparing finalization of "
544  "ThreadList '%s'", (*i)->name(), __name);
545  threw_exception = true;
546  }
547  }
548  if ( threw_exception ) {
549  throw cfte;
550  }
551  return can_finalize;
552 }
553 
554 
555 
556 
557 /** Finalize Threads.
558  * The threads are finalized.
559  * This operation is carried out unlocked. Lock it from the outside if needed.
560  * This is done because it is likely that this will be chained with other
561  * actions that require locking, thus you can lock the whole operation.
562  * @param finalizer thread finalizer to use to finalize the threads
563  */
564 void
566 {
567  bool error = false;
568  Exception me("One or more threads failed to finalize");
569  for (reverse_iterator i = rbegin(); i != rend(); ++i) {
570  try {
571  finalizer->finalize(*i);
572  } catch (CannotFinalizeThreadException &e) {
573  error = true;
574  me.append("Could not finalize thread '%s' in list '%s'", (*i)->name(), __name);
575  me.append(e);
576  }
577  try {
578  (*i)->finalize();
579  } catch (CannotFinalizeThreadException &e) {
580  error = true;
581  me.append("AspectIniFin called Thread[%s]::finalize() which failed", (*i)->name());
582  me.append(e);
583  } catch (Exception &e) {
584  me.append("AspectIniFin called Thread[%s]::finalize() which failed", (*i)->name());
585  me.append(e);
586  } catch (...) {
587  me.append("Thread[%s]::finalize() threw unsupported exception", (*i)->name());
588  }
589  }
590  if ( error ) {
591  throw me;
592  }
593 }
594 
595 
596 /** Cancel finalization on all threads.
597  */
598 void
600 {
601  MutexLocker lock(__finalize_mutex);
602 
603  for (reverse_iterator i = rbegin(); i != rend(); ++i) {
604  (*i)->cancel_finalize();
605  }
606 }
607 
608 
609 /** Set prepfin hold on all threads.
610  * This method will call Thread::set_prepfin_hold() for all threads in the list. If
611  * any of the threads fails to set prepfin hold then all thread were it has already
612  * been set are set to prepfin hold false.
613  * @param hold prepfin hold value
614  * @see Thread::set_prepfin_hold()
615  */
616 void
618 {
619  iterator i;
620  try {
621  for (i = begin(); i != end(); ++i) {
622  (*i)->set_prepfin_hold(hold);
623  }
624  } catch (Exception &e) {
625  // boom, we failed, at least one thread was already in the state of being prepared
626  // for finalization, rollback the hold for the threads were we already set it
627  for (iterator j = begin(); j != i; ++j) {
628  (*j)->set_prepfin_hold(false);
629  }
630  throw;
631  }
632 }
633 
634 
635 /** Force stop of all threads.
636  * This will call prepare_finalize(), finalize(), cancel() and join() on the
637  * list without caring about the return values in the prepare_finalize() step.
638  * @param finalizer thread finalizer to use to finalize the threads.
639  */
640 void
642 {
643  try {
644  prepare_finalize(finalizer);
645  stop();
646  finalize(finalizer);
647  } catch (Exception &e) {
648  // ignored
649  }
650 }
651 
652 
653 /** Name of the thread list.
654  * This can be used for better log output to identify the list that causes
655  * problems.
656  * @return name of thread list
657  */
658 const char *
660 {
661  return __name;
662 }
663 
664 
665 /** Set name of thread.
666  * Use parameters similar to printf().
667  * @param format format string
668  */
669 void
670 ThreadList::set_name(const char *format, ...)
671 {
672  va_list va;
673  va_start(va, format);
674 
675  char *tmpname;
676  if (vasprintf(&tmpname, format, va) != -1) {
677  free(__name);
678  __name = tmpname;
679  } else {
680  throw OutOfMemoryException("ThreadList::set_name(): vasprintf() failed");
681  }
682  va_end(va);
683 }
684 
685 
686 /** Check if list is sealed.
687  * If the list is sealed, no more writing operations are allowed and will trigger
688  * an exception.
689  * @return true, if list is sealed, false otherwise
690  */
691 bool
693 {
694  return __sealed;
695 }
696 
697 
698 /** Seal the list. */
699 void
701 {
702  __sealed = true;
703 }
704 
705 
706 /** Add thread to the front.
707  * Add thread to the beginning of the list.
708  * @param thread thread to add
709  */
710 void
712 {
713  if ( __sealed ) throw ThreadListSealedException("push_front");
714 
716  if ( __wnw_barrier) update_barrier();
717 }
718 
719 
720 /** Add thread to the front with lock protection.
721  * Add thread to the beginning of the list. The operation is protected
722  * by the thread list lock.
723  * The operation will succeed without blocking even
724  * if the list is currently locked. It will push the thread to an internal temporary
725  * list and will add the thread finally when the list is unlocked.
726  * @param thread thread to add
727  */
728 void
730 {
731  if ( __sealed ) throw ThreadListSealedException("push_front_locked");
732 
735  if ( __wnw_barrier) update_barrier();
736 }
737 
738 
739 /** Add thread to the end.
740  * Add thread to the end of the list.
741  * @param thread thread to add
742  */
743 void
745 {
746  if ( __sealed ) throw ThreadListSealedException("push_back");
747 
749  if ( __wnw_barrier) update_barrier();
750 }
751 
752 
753 /** Add thread to the end with lock protection.
754  * Add thread to the end of the list. The operation is protected
755  * by the thread list lock.
756  * The operation will succeed without blocking even
757  * if the list is currently locked. It will push the thread to an internal temporary
758  * list and will add the thread finally when the list is unlocked.
759  * @param thread thread to add
760  */
761 void
763 {
764  if ( __sealed ) throw ThreadListSealedException("push_back_locked");
765 
768  if ( __wnw_barrier) update_barrier();
769 }
770 
771 
772 /** Clear the list.
773  * Removes all elements.
774  */
775 void
777 {
778  if ( __sealed ) throw ThreadListSealedException("clear");
779 
781  if ( __wnw_barrier) update_barrier();
782 }
783 
784 
785 /** Remove with lock protection.
786  * @param thread thread to remove.
787  */
788 void
790 {
791  if ( __sealed ) throw ThreadListSealedException("remove_locked");
792 
794  if ( __wnw_barrier) update_barrier();
795 }
796 
797 
798 /** Remove with lock protection.
799  * @param thread thread to remove.
800  */
801 void
803 {
804  if ( __sealed ) throw ThreadListSealedException("remove_locked");
805 
808  if ( __wnw_barrier) update_barrier();
809 }
810 
811 
812 /** Remove first element. */
813 void
815 {
816  if ( __sealed ) throw ThreadListSealedException("pop_front");
817 
819  if ( __wnw_barrier) update_barrier();
820 }
821 
822 
823 /** Remove last element. */
824 void
826 {
827  if ( __sealed ) throw ThreadListSealedException("pop_back");
828 
830  if ( __wnw_barrier) update_barrier();
831 }
832 
833 
834 /** Erase element at given position.
835  * @param pos iterator marking the element to remove.
836  * @return iterator to element that follows pos
837  */
838 ThreadList::iterator
839 ThreadList::erase(iterator pos)
840 {
841  if ( __sealed ) throw ThreadListSealedException("erase");
842 
843  ThreadList::iterator rv = LockList<Thread *>::erase(pos);
844  if ( __wnw_barrier) update_barrier();
845  return rv;
846 }
847 
848 
849 /** Update internal barrier. */
850 void
851 ThreadList::update_barrier()
852 {
853  unsigned int num = 1;
854  for (iterator i = begin(); i != end(); ++i) {
855  if (! (*i)->flagged_bad() ) ++num;
856  }
857  delete __wnw_barrier;
858  __wnw_barrier = new InterruptibleBarrier(num);
859 }
860 
861 
862 /** Notify all threads of failed init. */
863 void
864 ThreadList::notify_of_failed_init()
865 {
866  for (ThreadList::iterator i = begin(); i != end(); ++i) {
867  (*i)->notify_of_failed_init();
868  }
869 }
870 
871 
872 } // end namespace fawkes
bool sealed()
Check if list is sealed.
RefPtr< Mutex > mutex() const
Get access to the internal mutex.
ThreadListSealedException(const char *operation)
Constructor.
Definition: thread_list.cpp:53
ThreadListNotSealedException(const char *format,...)
Constructor.
Definition: thread_list.cpp:72
LockList< Type > & operator=(const LockList< Type > &ll)
Copy values from another LockList.
Definition: lock_list.h:190
const char * name()
Name of the thread list.
unsigned int count()
Get number of threads this barrier will wait for.
Definition: barrier.cpp:181
virtual void init(Thread *thread)=0
This method is called by the ThreadManager for each newly added Thread.
void clear()
Clear the list.
void start()
Start threads.
void cancel_finalize()
Cancel finalization on all threads.
void push_back_locked(Thread *thread)
Add thread to the end with lock protection.
Mutex locking helper.
Definition: mutex_locker.h:33
void seal()
Seal the list.
virtual void finalize(Thread *thread)=0
Finalize a thread.
void set_prepfin_hold(bool hold)
Set prepfin hold on all threads.
void force_stop(ThreadFinalizer *finalizer)
Force stop of all threads.
A NULL pointer was supplied where not allowed.
Definition: software.h:34
void join()
Join threads.
Thread class encapsulation of pthreads.
Definition: thread.h:42
virtual void lock() const
Lock list.
void pop_back()
Remove last element.
bool prepare_finalize(ThreadFinalizer *finalizer)
Prepare finalize.
bool wait(unsigned int timeout_sec, unsigned int timeout_nanosec)
Wait for other threads.
Thread list sealed exception.
Definition: thread_list.h:44
void push_front_locked(Thread *thread)
Add thread to the front with lock protection.
virtual bool prepare_finalize(Thread *thread)=0
Prepare finalization of a thread.
List of threads.
Definition: thread_list.h:57
Thread cannot be initialized.
ThreadList & operator=(const ThreadList &tl)
Assignment operator.
ThreadList(const char *tlname="")
Constructor.
Definition: thread_list.cpp:94
Base class for exceptions in Fawkes.
Definition: exception.h:36
void remove_locked(Thread *thread)
Remove with lock protection.
ThreadList::iterator erase(iterator pos)
Erase element at given position.
void init(ThreadInitializer *initializer, ThreadFinalizer *finalizer)
Initialize threads.
void stop()
Stop threads.
Thread initializer interface.
List with a lock.
Definition: thread.h:40
void wakeup()
Wakeup all threads in list.
void finalize(ThreadFinalizer *finalizer)
Finalize Threads.
void pop_front()
Remove first element.
void append_va(const char *format, va_list va)
Append messages to the message list.
Definition: exception.cpp:361
static const unsigned int FLAG_BAD
Standard thread flag: &quot;thread is bad&quot;.
Definition: thread.h:65
~ThreadList()
Destructor.
void push_back(Thread *thread)
Add thread to the end.
RefPtr< ThreadList > passed_threads()
Get a list of threads that passed the barrier.
RefPtr&lt;&gt; is a reference-counting shared smartpointer.
Definition: refptr.h:49
void wakeup_unlocked()
Wakeup all threads in list.
Thread cannot be finalized.
void set_name(const char *format,...)
Set name of thread.
void try_recover(std::list< std::string > &recovered_threads)
Check if any of the bad barriers recovered.
void set_maintain_barrier(bool maintain_barrier)
Set if this thread list should maintain a barrier.
Mutex mutual exclusion lock.
Definition: mutex.h:32
void push_front(Thread *thread)
Add thread to the front.
void wakeup_and_wait(unsigned int timeout_sec=0, unsigned int timeout_nanosec=0)
Wakeup threads and wait for them to finish.
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
Definition: barrier.h:32
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
void cancel()
Cancel threads.
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
void remove(Thread *thread)
Remove with lock protection.
Thread finalizer interface.