Equalizer  1.2.1
thread.h
00001 
00002 /* Copyright (c) 2005-2011, 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 COBASE_THREAD_H
00019 #define COBASE_THREAD_H
00020 
00021 #include <co/base/api.h>      // COBASE_API definition
00022 #include <co/base/debug.h>    // debug macros in thread-safety checks
00023 #include <co/base/lock.h>     // member
00024 #include <co/base/monitor.h>  // member
00025 #include <co/base/threadID.h> // member
00026 
00027 #include <ostream>
00028 
00029 namespace co
00030 {
00031 namespace base
00032 {
00034     class Thread 
00035     {
00036     public:
00038         COBASE_API Thread();
00039 
00041         COBASE_API Thread( const Thread& from );
00042 
00044         COBASE_API virtual ~Thread();
00045 
00054         COBASE_API bool start();
00055 
00067         virtual bool init(){ return true; }
00068 
00077         virtual void run() = 0;
00078 
00087         COBASE_API virtual void exit();
00088 
00095         COBASE_API void cancel();
00096 
00103         COBASE_API bool join();
00104 
00114         bool isStopped() const { return ( _state == STATE_STOPPED ); }
00115 
00125         bool isRunning() const { return ( _state == STATE_RUNNING ); }
00126 
00132         COBASE_API bool isCurrent() const;
00133 
00135         COBASE_API static ThreadID getSelfThreadID();
00136 
00138         COBASE_API static void yield();
00139 
00141         static void pinCurrentThread();
00142 
00144         COBASE_API static void setName( const std::string& name );
00145 
00146     private:
00147         ThreadID _id;
00148 
00150         enum State
00151         {
00152             STATE_STOPPED,
00153             STATE_STARTING, // start() in progress
00154             STATE_RUNNING,
00155             STATE_STOPPING  // child no longer active, join() not yet called
00156         };
00157 
00158         Monitor< State > _state;
00159 
00160         static void* runChild( void* arg );
00161         void        _runChild();
00162 
00163         void _installCleanupHandler();
00164 
00165         static void _notifyStarted();
00166         static void _notifyStopping();
00167         friend void _notifyStopping( void* ); 
00168 
00169         friend std::ostream& operator << ( std::ostream& os, const Thread* );
00170     };
00171 
00173     std::ostream& operator << ( std::ostream& os, const Thread* thread );
00174 
00175 // thread-safety checks
00176 // These checks are for development purposes, to check that certain objects are
00177 // properly used within the framework. Leaving them enabled during application
00178 // development may cause false positives, e.g., when threadsafety is ensured
00179 // outside of the objects by the application.
00180 
00181 #ifndef NDEBUG
00182 #  define EQ_CHECK_THREADSAFETY
00183 #endif
00184 
00186 #define EQ_TS_VAR( NAME )                                   \
00187 public:                                                     \
00188     struct NAME ## Struct                                   \
00189     {                                                       \
00190         NAME ## Struct ()                                   \
00191             : extMutex( false ), inRegion( false )          \
00192             {}                                              \
00193         mutable co::base::ThreadID id;                      \
00194         mutable std::string name;                           \
00195         bool extMutex;                                      \
00196         mutable bool inRegion;                              \
00197     } NAME;                                                 \
00198 private:
00199 
00200 #ifdef EQ_CHECK_THREADSAFETY
00201 #  define EQ_TS_RESET( NAME ) NAME.id = co::base::ThreadID::ZERO; 
00202 
00203 #  define EQ_TS_THREAD( NAME )                                          \
00204     {                                                                   \
00205         if( NAME.id == co::base::ThreadID::ZERO )                       \
00206         {                                                               \
00207             NAME.id = co::base::Thread::getSelfThreadID();              \
00208             NAME.name = co::base::Log::instance().getThreadName();      \
00209             EQVERB << "Functions for " << #NAME                         \
00210                    << " locked to this thread" << std::endl;            \
00211         }                                                               \
00212         if( !NAME.extMutex && NAME.id != co::base::Thread::getSelfThreadID( )) \
00213         {                                                               \
00214             EQERROR << "Threadsafety check for " << #NAME               \
00215                     << " failed on object of type "                     \
00216                     << co::base::className( this ) << ", thread "       \
00217                     << co::base::Thread::getSelfThreadID() << " ("      \
00218                     << co::base::Log::instance().getThreadName() << ") != " \
00219                     << NAME.id << " (" << NAME.name << ")" << std::endl; \
00220             EQABORT( "Non-threadsave code called from two threads" );   \
00221         }                                                               \
00222     }
00223 
00224 #  define EQ_TS_NOT_THREAD( NAME )                                      \
00225     {                                                                   \
00226         if( !NAME.extMutex && NAME.id != co::base::ThreadID::ZERO )     \
00227         {                                                               \
00228             if( NAME.id == co::base::Thread::getSelfThreadID( ))        \
00229             {                                                           \
00230                 EQERROR << "Threadsafety check for not " << #NAME       \
00231                         << " failed on object of type "                 \
00232                         << co::base::className( this ) << std::endl;    \
00233                 EQABORT( "Code called from wrong thread" );             \
00234             }                                                           \
00235         }                                                               \
00236     }
00237 
00239     template< typename T > class ScopedThreadCheck : public NonCopyable
00240     {
00241     public:
00242         explicit ScopedThreadCheck( const T& data )
00243                 : _data( data )
00244             {
00245                 EQASSERTINFO( !data.inRegion,
00246                               "Another thread already in critical region" );
00247                 data.inRegion = true;
00248             }
00249         ~ScopedThreadCheck() 
00250             {
00251                 EQASSERTINFO( _data.inRegion,
00252                               "Another thread was in critical region" );
00253                 _data.inRegion = false;
00254             }
00255     private:
00256         const T& _data;
00257     };
00260 # define EQ_TS_SCOPED( NAME ) \
00261     co::base::ScopedThreadCheck< NAME ## Struct > scoped ## NAME ## Check(NAME);
00262 
00263 #else
00264 #  define EQ_TS_RESET( NAME ) {}
00265 #  define EQ_TS_THREAD( NAME ) {}
00266 #  define EQ_TS_NOT_THREAD( NAME ) {}
00267 #  define EQ_TS_SCOPED( NAME ) {}
00268 #endif
00269 
00270 }
00271 }
00272 #endif //COBASE_THREAD_H
Generated on Fri Jun 8 2012 15:44:32 for Equalizer 1.2.1 by  doxygen 1.8.0