thread.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef EQBASE_THREAD_H
00019 #define EQBASE_THREAD_H
00020
00021 #include <eq/base/base.h>
00022 #include <eq/base/lock.h>
00023
00024 #ifdef EQ_WIN32_SDP_JOIN_WAR
00025 # include <eq/base/monitor.h>
00026 #endif
00027
00028 #include <vector>
00029 #include <typeinfo>
00030 #include <sstream>
00031
00032 namespace eq
00033 {
00034 namespace base
00035 {
00036 class ExecutionListener;
00037 class ThreadPrivate;
00038
00042 class Thread
00043 {
00044 public:
00048 EQ_EXPORT Thread();
00049
00051 EQ_EXPORT virtual ~Thread();
00052
00063 EQ_EXPORT bool start();
00064
00075 virtual bool init(){ return true; }
00076
00085 virtual void* run() = 0;
00086
00095 EQ_EXPORT virtual void exit( void* retVal = 0 );
00096
00102 EQ_EXPORT void cancel();
00103
00112 EQ_EXPORT bool join( void** retVal=0 );
00113
00123 bool isStopped() const { return ( _state == STATE_STOPPED ); }
00124
00134 bool isRunning() const { return ( _state == STATE_RUNNING ); }
00135
00142 EQ_EXPORT bool isCurrent() const;
00143
00149 EQ_EXPORT static void addListener( ExecutionListener* listener );
00150
00156 EQ_EXPORT static bool removeListener( ExecutionListener* listener );
00157
00159 EQ_EXPORT static void removeAllListeners();
00160
00162 EQ_EXPORT static size_t getSelfThreadID();
00163
00165 static void pinCurrentThread();
00166
00167 private:
00168 ThreadPrivate* _data;
00170 enum State
00171 {
00172 STATE_STOPPED,
00173 STATE_STARTING,
00174 STATE_RUNNING,
00175 STATE_STOPPING
00176 };
00177
00178 State _state;
00179 Lock _syncChild;
00180
00181 #ifdef EQ_WIN32_SDP_JOIN_WAR
00182 Monitor<bool> _running;
00183 void* _retVal;
00184 #endif
00185
00186 static void* runChild( void* arg );
00187 void _runChild();
00188
00189 void _installCleanupHandler();
00190
00191 static void _notifyStarted();
00192 static void _notifyStopping();
00193 friend void _notifyStopping( void* );
00194
00195 friend std::ostream& operator << ( std::ostream& os, const Thread* );
00196 };
00197
00199 std::ostream& operator << ( std::ostream& os, const Thread* thread );
00200
00201
00202
00203
00204
00205
00206
00208 #define CHECK_THREAD_DECLARE( NAME ) \
00209 struct NAME ## Struct \
00210 { \
00211 NAME ## Struct () \
00212 : id( 0 ), extMutex( false ) \
00213 {} \
00214 mutable size_t id; \
00215 bool extMutex; \
00216 } NAME; \
00217
00218 #ifdef EQ_CHECK_THREADSAFETY
00219 # define CHECK_THREAD_RESET( NAME ) NAME.id = 0;
00220
00221 # define CHECK_THREAD( NAME ) \
00222 { \
00223 if( NAME.id == 0 ) \
00224 { \
00225 NAME.id = eq::base::Thread::getSelfThreadID(); \
00226 EQVERB << "Functions for " << #NAME \
00227 << " locked to this thread" << std::endl; \
00228 } \
00229 if( !NAME.extMutex && NAME.id != eq::base::Thread::getSelfThreadID( )) \
00230 { \
00231 EQERROR << "Threadsafety check for " << #NAME \
00232 << " failed on object of type " \
00233 << typeid(*this).name() << std::endl; \
00234 EQABORT( "Non-threadsave code called from two threads" ); \
00235 } \
00236 }
00237
00238 # define CHECK_NOT_THREAD( NAME ) \
00239 { \
00240 if( !NAME.extMutex && NAME.id != 0 ) \
00241 { \
00242 if( NAME.id == eq::base::Thread::getSelfThreadID( )) \
00243 { \
00244 EQERROR << "Threadsafety check for not " << #NAME \
00245 << " failed on object of type " \
00246 << typeid(*this).name() << std::endl; \
00247 EQABORT( "Code called from wrong thread" ); \
00248 } \
00249 } \
00250 }
00251 #else
00252 # define CHECK_THREAD_RESET( NAME )
00253 # define CHECK_THREAD( NAME )
00254 # define CHECK_NOT_THREAD( NAME )
00255 #endif
00256
00257 }
00258 }
00259 #endif //EQBASE_THREAD_H