Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
Thread.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_Thread_h_ 00003 #define INCLUDED_Thread_h_ 00004 00005 #ifdef PLATFORM_APERIOS 00006 # warning Thread class is not Aperios compatable 00007 #else 00008 00009 #include "Shared/Resource.h" 00010 #include <stddef.h> 00011 00012 struct timespec; 00013 00014 //! provides Thread related data structures 00015 namespace ThreadNS { 00016 //! an inter-thread lock -- doesn't work across processes, only threads within a process. (see MutexLock for inter-process locks) 00017 class Lock : public Resource { 00018 public: 00019 Lock(); //!< constructor 00020 //explicit Lock(const Lock& l); //!< copy constructor -- shallow copy, share a lock, is handy for locking over a scope!!! (lock is automatically obtained on copy -- to avoid autolock, pass false to the two-argument constructor: Lock(const Lock& l, bool autolock) ) 00021 //Lock(const Lock& l, bool autolock); //!< copy constructor -- shallow copy, share a lock, is handy for locking over a scope!!! 00022 //Lock& operator=(const Lock& l); //!< assignment -- dereference (and release) any previous lock, take on the new storage (shallow copy!) 00023 ~Lock(); //!< destructor -- dereference and release (if any references remain) 00024 void lock(); //!< block until lock is obtained 00025 bool trylock(); //!< see if lock is available 00026 void unlock(); //!< release lock, if held 00027 unsigned int getInstanceLockLevel() const { return locklevel; } //!< returns the lock level of the local instance of Lock (as opposed to the lock storage structure, which might be shared with other Lock instances) 00028 unsigned int getLockLevel() const; //!< returns the lock level of the lock storage itself, the sum of all instance's lock levels 00029 protected: 00030 friend class MarkScope; 00031 friend class Condition; 00032 virtual void useResource(Resource::Data&) { lock(); } 00033 virtual void releaseResource(Resource::Data&) { unlock(); } 00034 00035 class LockStorage; //!< this internal class will hold the system-dependent lock information 00036 static LockStorage* glock; //!< The global lock to protect Locks sharing #mylock's 00037 LockStorage* mylock; //!< This lock's implementation 00038 static void setup(); //!< creates a new #glock if it is currently NULL (should be called by the Lock() constructor) 00039 unsigned int locklevel; //!< the current lock level from this Lock, may differ from #mylock's lock level if several Locks are sharing a storage! 00040 private: 00041 Lock(const Lock& l); //!< don't call 00042 Lock& operator=(const Lock& l); //!< don't call 00043 }; 00044 00045 //! Provides an inter-thread signaling and synchronization mechanism 00046 class Condition { 00047 public: 00048 Condition(); //!< constructor 00049 ~Condition(); //!< destructor 00050 00051 void broadcast() const; //!< wake up all threads waiting on the condition 00052 void signal() const; //!< wake up a single thread waiting on the condition (which thread is unspecified) 00053 bool timedwait(Lock& l, const timespec* abstime) const; //!< wait for at most @a abstime for the condition before giving up (return true if condition found) 00054 void wait(Lock& l) const; //!< wait for condition 00055 protected: 00056 class ConditionStorage; //!< internal class to hold system-dependent information 00057 ConditionStorage* mycond; //!< the condition's implementation storage 00058 private: 00059 Condition(const Condition& l); //!< don't call 00060 Condition& operator=(const Condition& l); //!< don't call 00061 }; 00062 } 00063 00064 //! Provides a nice wrapping of pthreads library 00065 /*! If you need to provide cleanup functions on stop(), cancelled(), etc., you 00066 * should override the destructor to stop and join so that you can be assured 00067 * that your cleanup will be called if the thread is auto-destructed by going out of scope */ 00068 class Thread { 00069 public: 00070 typedef ThreadNS::Lock Lock; //!< shorthand for pthread lock wrapper 00071 00072 Thread(); //!< constructor, does not start thread by itself (although subclasses may) 00073 virtual ~Thread()=0; //!< destructor, will stop and join the thread, but you should override it to do the same if you provide any cleanup functions 00074 00075 //! requests that the thread be started, if not already running (you need to create a separate instances if you want to run multiple copies) 00076 virtual void start(); 00077 00078 //! sends a signal to the thread which will interrupt any sleep calls (and trigger interrupted() to be called within the thread) 00079 virtual void interrupt(); 00080 00081 //! requests that the thread be stopped gracefully, if running. 00082 /*! A cancel flag is sent, and the thread will be stopped at next cancel point, defined 00083 * by whenever testCancel(), or a set of other system functions, are called. 00084 * See your system's pthread_testcancel() manual page for a list of cancel points. 00085 * 00086 * This function may imply a call to interrupt() on systems which have extremely limited 00087 * system cancel points. Currently, this consists of only Mac OS X. There is hope that 00088 * additional cancellation points will be enabled on this system: 00089 * http://lists.apple.com/archives/darwin-kernel/2004/Jan/msg00032.html 00090 * 00091 * @see pushNoCancel(), popNoCancel() */ 00092 virtual void stop(); 00093 00094 //! sends a SIGUSR1 to the thread, breaking its execution, but still allowing handle_exit (and thus cancelled()) to be called. 00095 /*! Beware if your thread uses mutual exclusion locks, this can cause the thread to terminate while still holding locks */ 00096 virtual void kill(); 00097 00098 //! detaches thread and sends SIGSTOP, which immediately halts the thread without any chance for cleanup 00099 /*! Beware if your thread uses mutual exclusion locks, this @b will cause the thread to terminate while still holding locks. */ 00100 virtual void murder(); 00101 00102 //! sends a signal to the thread 00103 virtual void sendSignal(int sig); 00104 00105 //! blocks calling thread until this Thread has terminated, via one means or another; return value is final return value by the thread 00106 virtual void * join(); 00107 00108 //! indicates whether start() has been called (but may be some delay before isRunning() is true...) 00109 virtual bool isStarted() const { return started; } 00110 00111 //! indicates whether the thread is currently alive and running, implies isStarted() 00112 virtual bool isRunning() const { return running; } 00113 00114 //! returns the Thread object for the current thread (or NULL for the main thread) 00115 static Thread* getCurrent() ; 00116 00117 //! should be called before any threads are created to allow some global thread-specific data to be set up 00118 static void initMainThread(); 00119 //! should be called if you no longer expect to have any threads in use 00120 static void releaseMainThread(); 00121 00122 //! should be called whenever a critical section has been entered (i.e. mutex obtained) -- prevents cancel from occurring until popNoCancel() is called 00123 static void pushNoCancel(); 00124 //! should be called whenever a critical section is left (i.e. mutex released) -- if it was the last one, tests cancellability as well 00125 static void popNoCancel(); 00126 00127 //! returns #group 00128 void* getGroup() const { return group; } 00129 //! assigns #group, which will then be inherited by any threads instantiated by this one (the constructor call queries the current thread, no the start() or launch()) 00130 void setGroup(void* g) { group=g; } 00131 00132 protected: 00133 //! called by launch() when thread is first entered, return false to cancel launch (set #returnValue as well if you care) 00134 virtual bool launched() { return true; } 00135 //! called by launch() once the thread has been set up; when this returns, the thread ends, see runloop() 00136 /*! Default implementation repeatedly calls runloop(), usleep(), and testCancel(). 00137 * If you override, you should also be sure to call testCancel occasionally in order to support stop() 00138 * If function returns a value, that value overrides #returnValue. If cancel occurs, #returnValue is used. */ 00139 virtual void * run(); 00140 //! override this as a convenient way to define your thread -- return the number of *micro*seconds to sleep before the next call; return -1U to indicate end of processing 00141 virtual unsigned int runloop() { return -1U; } 00142 //! called when handle_exit() is triggered, either by the thread being cancelled, or when run() has returned voluntarily 00143 virtual void cancelled() {} 00144 00145 //! checks to see if stop() has been called, and if so, will exit the thread (passing through handle_exit() first) 00146 virtual void testCancel(); 00147 //! thread entry point -- calls launched() on the thread (as indicated by @a msg), and then run() 00148 static void * launch(void * msg); 00149 //! indicates kill() has been called (or SIGUSR1 was sent from some other source) while launch() was still running 00150 static void handle_launch_signal(int sig); 00151 //! indicates kill() has been called (or SIGUSR1 was sent from some other source) 00152 static void handle_signal(int sig); 00153 //! indicates the thread is exiting, either voluntary (run() returned), stop(), or kill() -- calls cancelled() for the thread as indicated by @a th 00154 static void handle_exit(void * th); 00155 00156 //! called by handleInterrupt() in target thread following call to interrupt(), assuming thread has not been cancelled (which can intercept the interrupt) 00157 virtual void interrupted() {} 00158 00159 //! called by SIGALRM signal handler installed by interrupt() just before it posts the corresponding SIGALRM 00160 /*! tests for thread cancel condition before calling on to interrupted() */ 00161 static void handleInterrupt(int signal); 00162 00163 //! emit a warning that the last thread exited while the self-pointer thread-specific key still exists (need to call releaseMainThread() or handle_exit()) 00164 static void warnSelfUndestructed(void* msg); 00165 00166 //! stores the actual pthread data fields 00167 struct Threadstorage_t * pt; 00168 //! set to true once start() has been called, set back to false by handle_exit(), or by murder() itself 00169 bool started; 00170 //! set to true once launch() has been called, set back to false by handle_exit(), or by murder() itself 00171 bool running; 00172 //! indicates the value to be returned by the thread entry point (and thus passed back to join()) -- set this in runloop() or launched(), overridden by run()'s return value 00173 void * returnValue; 00174 //! depth of the pushNoCancel() stack 00175 unsigned int noCancelDepth; 00176 //! cancel status at root of no-cancel stack (may be no-cancel through and through) 00177 int cancelOrig; 00178 00179 //! indicates a common group of threads, inherited from the thread which created this one, default NULL if created from main thread 00180 void* group; 00181 00182 private: 00183 Thread(const Thread& r); //!< don't call, not a well defined operation 00184 Thread& operator=(const Thread& r); //!< don't call, not a well defined operation 00185 }; 00186 00187 #endif //Aperios check 00188 00189 #endif 00190 00191 /*! @file 00192 * @brief Describes the Thread class and its AutoThread templated subclass 00193 * @author ejt (Creator) 00194 * 00195 * $Author: ejt $ 00196 * $Name: tekkotsu-4_0 $ 00197 * $Revision: 1.15 $ 00198 * $State: Exp $ 00199 * $Date: 2007/10/12 16:55:04 $ 00200 */ 00201 |
Tekkotsu v4.0 |
Generated Thu Nov 22 00:54:56 2007 by Doxygen 1.5.4 |