Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Thread.h

Go 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 //! provides Thread related data structures
00013 namespace ThreadNS {
00014   //! an inter-thread lock -- doesn't work across processes, only threads within a process.  (see MutexLock for inter-process locks)
00015   class Lock : public Resource {
00016   public:
00017     Lock(); //!< constructor
00018     //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) )
00019     //Lock(const Lock& l, bool autolock); //!< copy constructor -- shallow copy, share a lock, is handy for locking over a scope!!!
00020     //Lock& operator=(const Lock& l); //!< assignment -- dereference (and release) any previous lock, take on the new storage (shallow copy!)
00021     ~Lock(); //!< destructor -- dereference and release (if any references remain)
00022     void lock(); //!< block until lock is obtained
00023     bool trylock(); //!< see if lock is available
00024     void unlock(); //!< release lock, if held
00025     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)
00026     unsigned int getLockLevel() const; //!< returns the lock level of the lock storage itself, the sum of all instance's lock levels
00027   protected:
00028     friend class MarkScope;
00029     virtual void useResource(Resource::Data&) { lock(); }
00030     virtual void releaseResource(Resource::Data&) { unlock(); }
00031     
00032     class LockStorage; //!< this internal class will hold the system-dependent lock information
00033     static LockStorage* glock; //!< The global lock to protect Locks sharing #mylock's
00034     LockStorage* mylock; //!< This lock's implementation
00035     static void setup(); //!< creates a new #glock if it is currently NULL (should be called by the Lock() constructor)
00036     unsigned int locklevel; //!< the current lock level from this Lock, may differ from #mylock's lock level if several Locks are sharing a storage!
00037   private:
00038     Lock(const Lock& l); //!< don't call
00039     Lock& operator=(const Lock& l); //!< don't call
00040   };  
00041 } 
00042 
00043 //! Provides a nice wrapping of pthreads library
00044 /*! If you need to provide cleanup functions on stop(), cancelled(), etc., you
00045  *  should override the destructor to stop and join so that you can be assured
00046  *  that your cleanup will be called if the thread is auto-destructed by going out of scope */
00047 class Thread {
00048 public:
00049   typedef ThreadNS::Lock Lock; //!< shorthand for pthread lock wrapper
00050 
00051   Thread(); //!< constructor, does not start thread by itself (although subclasses may)
00052   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
00053   
00054   //! requests that the thread be started, if not already running (you need to create a separate instances if you want to run multiple copies)
00055   virtual void start();
00056   
00057   //! requests that the thread be stopped gracefully, if running.
00058   /*! A cancel flag is sent, and the thread will be stopped at next cancel point, defined
00059    *  by whenever testCancel(), or a set of other system functions, are called.
00060    *  See your system's pthread_testcancel() manual page for a list of cancel points.
00061    *  @see pushNoCancel(), popNoCancel() */
00062   virtual void stop();
00063   
00064   //! sends a SIGUSR1 to the thread, breaking its execution, but still allowing handle_exit (and thus cancelled()) to be called.
00065   /*! Beware if your thread uses mutual exclusion locks, this can cause the thread to terminate while still holding locks */
00066   virtual void kill();
00067   
00068   //! detaches thread and sends SIGSTOP, which immediately halts the thread without any chance for cleanup
00069   /*! Beware if your thread uses mutual exclusion locks, this @b will cause the thread to terminate while still holding locks. */
00070   virtual void murder();
00071   
00072   //! sends a signal to the thread
00073   virtual void sendSignal(int sig);
00074   
00075   //! blocks calling thread until this Thread has terminated, via one means or another; return value is final return value by the thread
00076   virtual void * join();
00077   
00078   //! indicates whether start() has been previously called
00079   virtual bool isRunning() const { return running; }
00080   
00081   //! returns the Thread object for the current thread (or NULL for the main thread)
00082   static Thread* getCurrent() ;
00083   
00084   //! should be called before any threads are created to allow some global thread-specific data to be set up
00085   static void initMainThread();
00086   //! should be called if you no longer expect to have any threads in use
00087   static void releaseMainThread();
00088 
00089   //! should be called whenever a critical section has been entered (i.e. mutex obtained) -- prevents cancel from occurring until popNoCancel() is called
00090   static void pushNoCancel();
00091   //! should be called whenever a critical section is left (i.e. mutex released) -- if it was the last one, tests cancellability as well
00092   static void popNoCancel();
00093   
00094 protected:
00095   //! called by launch() when thread is first entered, return false to cancel launch (set #returnValue as well if you care)
00096   virtual bool launched() { return true; }
00097   //! called by launch() once the thread has been set up; when this returns, the thread ends, see runloop()
00098   /*! Default implementation repeatedly calls runloop(), usleep(), and testCancel().
00099    *  If you override, you should also be sure to call testCancel occasionally in order to support stop()
00100    *  If function returns a value, that value overrides #returnValue.  If cancel occurs, #returnValue is used. */
00101   virtual void * run();
00102   //! 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
00103   virtual unsigned int runloop() { return -1U; }
00104   //! called when handle_exit() is triggered, either by the thread being cancelled, or when run() has returned voluntarily
00105   virtual void cancelled() {}
00106   
00107   //! checks to see if stop() has been called, and if so, will exit the thread (passing through handle_exit() first)
00108   virtual void testCancel();
00109   //! thread entry point -- calls launched() on the thread (as indicated by @a msg), and then run()
00110   static void * launch(void * msg);
00111   //! indicates kill() has been called (or SIGUSR1 was sent from some other source) while launch() was still running
00112   static void handle_launch_signal(int sig);
00113   //! indicates kill() has been called (or SIGUSR1 was sent from some other source)
00114   static void handle_signal(int sig);
00115   //! indicates the thread is exiting, either voluntary (run() returned), stop(), or kill() -- calls cancelled() for the thread as indicated by @a th
00116   static void handle_exit(void * th);
00117 
00118   //! emit a warning that the last thread exited while the self-pointer thread-specific key still exists (need to call releaseMainThread() or handle_exit())
00119   static void warnSelfUndestructed(void* msg);
00120 
00121   //! stores the actual pthread data fields
00122   struct Threadstorage_t * pt;
00123   //! set to true once start has been called, set back to false by handle_exit(), or by murder() itself
00124   bool running;
00125   //! 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
00126   void * returnValue;
00127   //! depth of the pushNoCancel() stack
00128   unsigned int noCancelDepth;
00129   //! cancel status at root of no-cancel stack (may be no-cancel through and through)
00130   int cancelOrig;
00131 
00132 private:
00133   Thread(const Thread& r); //!< don't call, not a well defined operation
00134   Thread& operator=(const Thread& r); //!< don't call, not a well defined operation
00135 };
00136 
00137 #endif //Aperios check
00138 
00139 #endif
00140 
00141 /*! @file
00142 * @brief Describes the Thread class and its AutoThread templated subclass
00143 * @author ejt (Creator)
00144 *
00145 * $Author: ejt $
00146 * $Name: tekkotsu-3_0 $
00147 * $Revision: 1.12 $
00148 * $State: Exp $
00149 * $Date: 2006/06/16 21:49:23 $
00150 */
00151 

Tekkotsu v3.0
Generated Wed Oct 4 00:03:46 2006 by Doxygen 1.4.7