thread.H

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright  2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #ifndef ARCHON_UTILITIES_THREAD_H
00021 #define ARCHON_UTILITIES_THREAD_H
00022 
00023 #include <list>
00024 
00025 #include <sys/select.h> // fd_set
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 &); // Hide
00336       Thread &operator=(const Thread &); // Hide
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         // std::swap is used to arrange for the destruction of the
00377         // objects o upon exit of this method.
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         // std::swap is used to arrange for the destruction of the
00404         // objects o and a upon exit of this method.
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         // std::swap is used to arrange for the destruction of the
00447         // objects a upon exit of this method.
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

Generated on Sun Jul 30 22:55:45 2006 for Archon by  doxygen 1.4.4