00001 // DOCUMENT: Thread-Class 00002 // VERSION: $Revision: 1.5 $ 00003 // DATE: $Date: 2007-10-26 23:09:19 $ 00004 // AUTHOR: M.Beranek 00005 // COPYRIGHT: M.Beranek 00006 00007 #ifndef _THREAD_H 00008 #define _THREAD_H 00009 00010 #include <pthread.h> 00011 00012 namespace SmtpThread 00013 { 00014 /** 00015 * Thread-Class. 00016 * 00017 * This abstract class wraps a class around a threading function. 00018 * 00019 * Threading is startet through calling 'Start', which sets 00020 * the protected member-variable '_isRunning'. The state of 00021 * the thread can be checked with the member-function 00022 * 'isRunning'. 00023 * 00024 * You must overwrite the method 'Execute' to do 00025 * something usefull within the thread. 00026 * 00027 * 'Execute' should be constructed as an endless loop like: 00028 * 00029 * <code> 00030 * void InheritedClassname::Execute( void * arg )<br> 00031 * {<br> 00032 * while( _isRunning )<br> 00033 * {<br> 00034 * // do something...<br> 00035 * }<br> 00036 * }<br> 00037 * </code> 00038 * 00039 * When 'Start' is called, it starts the thread and executes 00040 * 'Setup' and 'Execute'. 00041 * 00042 * To stop threading, simply call 'Stop'. 00043 */ 00044 class Thread 00045 { 00046 public: 00047 00048 /** 00049 * Constructor. 00050 */ 00051 Thread(); 00052 00053 /** 00054 * Destructor. 00055 * 00056 * NOTE: Under normal conditions I would use a purely virtual 00057 * destructor. But unfortunately most people (me too) often forget 00058 * to call the 'Stop' member-function in the destructor of the 00059 * derived classes. 00060 * 00061 * So calling delete on an object, which still has a running 00062 * thread, may not behave well, especially when the destructor 00063 * removes members of the object, while the thread is trying to 00064 * access them. 00065 * 00066 * So, I implemented a non-virtual destructor, which stops 00067 * threading, when the thread is still running. This will cause 00068 * most compilers to issue a warning, but it seems to be the 00069 * easiest way, to get your code working... ;) 00070 * 00071 */ 00072 ~Thread(); 00073 00074 /** 00075 * Start threading. 00076 * @param void* arg typeless argument. 00077 * @return int exit-code of 'pthread_create' 00078 */ 00079 int Start(void* arg); 00080 00081 /** 00082 * Returns the thread-id. 00083 * @return pthread_t thread-id 00084 */ 00085 pthread_t getThreadId(); 00086 00087 /** 00088 * Checks, whether or not the thread is running. 00089 * @return bool true / false = running / not running 00090 */ 00091 bool isRunning(); 00092 00093 /** 00094 * Stop threading. 00095 */ 00096 void Stop(); 00097 00098 00099 protected: 00100 00101 /** 00102 * Gets called immediatly after "EntryPoint". 00103 * Calls "Setup" and "Execute". 00104 * @param void* arg typeless argument. 00105 */ 00106 int Run(void * arg); 00107 00108 /** 00109 * This is the entrypoint for threading. 00110 * This function must be declared as "static", because the pthread-library 00111 * expects a normal C-type-function as an entrypoint. 00112 * 00113 * Parameters are passed as pointer to void and are the same as passed 00114 * to "Start". 00115 * 00116 * @param void* arg typeless argument. 00117 */ 00118 static void * EntryPoint( void * ); 00119 00120 /** 00121 * Initializes some thread-variables and sets up a mutex. 00122 * The mutex can be accessed through the member-varaible 00123 * "_mutex". 00124 */ 00125 virtual void Setup(); 00126 00127 /** 00128 * The main threading-functionality goes here. 00129 * You should create an endless loop like: 00130 * 00131 * <code> 00132 * while( _isRunning) 00133 * { 00134 * // do something usefull... 00135 * } 00136 * </code> 00137 * 00138 * Parameters are passed as pointer to void and are the same as passed 00139 * to "Start". 00140 * 00141 * @param void* arg typeless argument. 00142 */ 00143 virtual void Execute( void * ); 00144 00145 /** 00146 * Helper to initialize the parameters provided to "Start". 00147 */ 00148 void * Arg() const 00149 { 00150 return _arg; 00151 } 00152 00153 /** 00154 * Initiallizes the parameters passed to "Start". 00155 * 00156 * @param void* a typeless argument. 00157 */ 00158 void Arg( void * a ) 00159 { 00160 _arg = a; 00161 } 00162 00163 /** Wether or not the thread is running. */ 00164 bool _isRunning; 00165 00166 /** Mutex. */ 00167 pthread_mutex_t _mutex; 00168 00169 /** 00170 * Locks the mutex "_mutex". 00171 * 00172 * NOTE: Use with care, cause it might get you a deadlock! 00173 * 00174 * @see Thread::releaseLock 00175 */ 00176 void getLock(); 00177 00178 /** 00179 * Unlocks the mutex "_mutex". 00180 * 00181 * @see Thread::getLock 00182 */ 00183 void releaseLock(); 00184 00185 00186 private: 00187 00188 /** Thread-ID. */ 00189 pthread_t _ThreadId; 00190 00191 /** Parameters passed to "Start", */ 00192 void * _arg; 00193 00194 00195 }; 00196 00197 } 00198 00199 #endif /* _THREAD_H */ 00200
1.5.1