thread.h

00001 
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #ifndef EQBASE_THREAD_H
00019 #define EQBASE_THREAD_H
00020 
00021 #include <eq/base/base.h>     // EQ_EXPORT definition
00022 #include <eq/base/lock.h>     // member
00023 
00024 #ifdef EQ_WIN32_SDP_JOIN_WAR
00025 #  include <eq/base/monitor.h> // member
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, // start() in progress
00174             STATE_RUNNING,
00175             STATE_STOPPING  // child no longer active, join() not yet called
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 // thread-safety checks
00202 // These checks are for development purposes, to check that certain objects are
00203 // properly used within the framework. Leaving them enabled during application
00204 // development may cause false positives, e.g., when threadsafety is ensured
00205 // outside of the objects by the application.
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
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8