00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ARCHON_UTILITIES_THREAD_H
00021 #define ARCHON_UTILITIES_THREAD_H
00022
00023 #include <list>
00024
00025 #include <sys/select.h>
00026
00027 #include <archon/util/exception.H>
00028 #include <archon/util/time.H>
00029 #include <archon/util/condition.H>
00030 #include <archon/util/ref.H>
00031
00032 namespace Archon
00033 {
00034 namespace Utilities
00035 {
00036 using namespace std;
00037
00098 struct Thread: virtual RefObjectBase
00099 {
00100 struct ThreadException: virtual Exception {};
00101
00102 struct AlreadyStartedException: ThreadException
00103 {
00104 AlreadyStartedException(string l): Exception(l) {}
00105 };
00106
00107 struct NotStartedException: ThreadException
00108 {
00109 NotStartedException(string l): Exception(l) {}
00110 };
00111
00112
00127 template<typename T>
00128 static Ref<Thread> run(Ref<T>, void (T::*)(), bool start = true);
00129
00138 template<typename T, typename U>
00139 static Ref<Thread> run(Ref<T>, void (T::*)(U), U, bool start = true);
00140
00153 template<typename T>
00154 static Ref<Thread> run(void (*)(T), T, bool start = true);
00155
00165 static Ref<Thread> run(void (*)(), bool start = true);
00166
00191 static void start(Ref<Thread>) throw(AlreadyStartedException);
00192
00199 void wait() throw(NotStartedException, UnexpectedException);
00200
00220 void terminate();
00221
00230 static Ref<Thread> self();
00231
00240 static void sleep(const Time &period) throw(UnexpectedException);
00241
00250 static void sleepUntil(const Time &timeout) throw(UnexpectedException);
00251
00262 static void acceptTermination() throw(UnexpectedException);
00263
00273 static void selfResurrect();
00274
00295 static void mainExitWait();
00296
00297 protected:
00302 virtual void main() = 0;
00303
00308 Thread();
00309
00310 virtual ~Thread();
00311
00312 private:
00313 friend struct Condition;
00314
00315 struct SelfThread;
00316
00317 pthread_t pthread;
00318 bool started;
00319 bool terminated;
00320 Condition termination;
00321
00322 volatile bool terminateRequest;
00323 Mutex waitConditionMutex;
00324 Condition *waitCondition;
00325
00326 static void selfKeyDestroy(void *) throw();
00327 static void selfKeyAlloc() throw();
00328 static void registerSelf(Thread *);
00329
00330 static void *entry(Thread *thread) throw();
00331
00332 static void activate(Thread *);
00333 static void deactivate(Thread *);
00334
00335 Thread(const Thread &);
00336 Thread &operator=(const Thread &);
00337 };
00338
00339
00340
00346 struct Semaphore
00347 {
00348 Semaphore(int initialValue=1): value(initialValue), nonZero(mutex) {}
00349
00353 void down() throw(UnexpectedException);
00354
00358 void up();
00359
00360 private:
00361 int value;
00362 Mutex mutex;
00363 Condition nonZero;
00364 };
00365
00366
00367
00368
00369 template<typename T> struct MethodVoidRunner: Thread
00370 {
00371 Ref<T> o;
00372 void (T::*m)();
00373 MethodVoidRunner(Ref<T> o, void (T::*m)()): o(o), m(m) {}
00374 void main()
00375 {
00376
00377
00378 Ref<T> p;
00379 p.swap(o);
00380 (p.get()->*m)();
00381 }
00382 };
00383
00384 template<typename T>
00385 Ref<Thread> Thread::run(Ref<T> o, void (T::*m)(), bool s)
00386 {
00387 Ref<MethodVoidRunner<T> > r = new MethodVoidRunner<T>(o, m);
00388 if(s) Thread::start(r);
00389 return r;
00390 }
00391
00392
00393
00394 template<typename T, typename U> struct MethodArgRunner: Thread
00395 {
00396 Ref<T> o;
00397 void (T::*m)(U);
00398 U a;
00399 MethodArgRunner(Ref<T> o, void (T::*m)(U), U a): o(o), m(m), a(a) {}
00400
00401 void main()
00402 {
00403
00404
00405 Ref<T> p;
00406 U b;
00407 std::swap(o, p);
00408 std::swap(a, b);
00409 (p.get()->*m)(b);
00410 }
00411 };
00412
00413 template<typename T, typename U>
00414 Ref<Thread> Thread::run(Ref<T> o, void (T::*m)(U), U a, bool s)
00415 {
00416 Ref<MethodArgRunner<T, U> > r = new MethodArgRunner<T, U>(o, m, a);
00417 if(s) Thread::start(r);
00418 return r;
00419 }
00420
00421
00422
00423 struct FuncVoidRunner: Thread
00424 {
00425 void (*f)();
00426 FuncVoidRunner(void (*f)()): f(f) {}
00427 void main() { (*f)(); }
00428 };
00429
00430 inline Ref<Thread> Thread::run(void (*f)(), bool s)
00431 {
00432 Ref<FuncVoidRunner> r = new FuncVoidRunner(f);
00433 if(s) Thread::start(r);
00434 return r;
00435 }
00436
00437
00438
00439 template<typename T> struct FuncArgRunner: Thread
00440 {
00441 void (*f)(T);
00442 T a;
00443 FuncArgRunner(void (*f)(T), T a): f(f), a(a) {}
00444 void main()
00445 {
00446
00447
00448 T b;
00449 std::swap(a, b);
00450 (*f)(b);
00451 }
00452 };
00453
00454 template<typename T>
00455 Ref<Thread> Thread::run(void (*f)(T), T a, bool s)
00456 {
00457 Ref<FuncArgRunner<T> > r = new FuncArgRunner<T>(f, a);
00458 if(s) Thread::start(r);
00459 return r;
00460 }
00461 }
00462 }
00463
00464 #endif // ARCHON_UTILITIES_THREAD_H