Equalizer  1.3.1-git
thread.h
00001 
00002 /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com>
00003  *               2012, Marwan Abdellah <marwan.abdellah@epfl.ch>
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #ifndef LUNCHBOX_THREAD_H
00020 #define LUNCHBOX_THREAD_H
00021 
00022 #include <lunchbox/api.h>         // LUNCHBOX_API definition
00023 #include <lunchbox/debug.h>       // debug macros in thread-safety checks
00024 #include <lunchbox/nonCopyable.h> // base class
00025 #include <lunchbox/threadID.h>    // member
00026 #include <lunchbox/types.h>
00027 
00028 #include <ostream>
00029 
00030 namespace lunchbox
00031 {
00032 namespace detail { class Thread; }
00033 
00035     class Thread
00036     {
00037     public:
00039         enum Affinity
00040         {
00041             CORE = 1, 
00042             SOCKET = -65536, 
00043             SOCKET_MAX = -1024 
00044         };
00045 
00047         LUNCHBOX_API Thread();
00048 
00050         LUNCHBOX_API Thread( const Thread& from );
00051 
00053         LUNCHBOX_API virtual ~Thread();
00054 
00063         LUNCHBOX_API virtual bool start();
00064 
00076         virtual bool init(){ return true; }
00077 
00086         virtual void run() = 0;
00087 
00096         LUNCHBOX_API virtual void exit();
00097 
00104         LUNCHBOX_API void cancel();
00105 
00112         LUNCHBOX_API bool join();
00113 
00123         LUNCHBOX_API bool isStopped() const;
00124 
00134         LUNCHBOX_API bool isRunning() const;
00135 
00141         LUNCHBOX_API bool isCurrent() const;
00142 
00144         LUNCHBOX_API static ThreadID getSelfThreadID();
00145 
00147         LUNCHBOX_API static void yield();
00148 
00150         static void pinCurrentThread();
00151 
00153         LUNCHBOX_API static void setName( const std::string& name );
00154 
00165         LUNCHBOX_API static void setAffinity( const int32_t affinity );
00166 
00167     private:
00168         detail::Thread* const _impl;
00169 
00170         static void* runChild( void* arg );
00171         void        _runChild();
00172 
00173         void _installCleanupHandler();
00174 
00175         static void _notifyStarted();
00176         static void _notifyStopping();
00177         friend void _notifyStopping( void* ); 
00178     };
00179 
00180 // thread-safety checks
00181 // These checks are for development purposes, to check that certain objects are
00182 // properly used within the framework. Leaving them enabled during application
00183 // development may cause false positives, e.g., when threadsafety is ensured
00184 // outside of the objects by the application.
00185 
00186 #ifndef NDEBUG
00187 #  define LB_CHECK_THREADSAFETY
00188 #endif
00189 
00191 #define LB_TS_VAR( NAME )                                   \
00192 public:                                                     \
00193     struct NAME ## Struct                                   \
00194     {                                                       \
00195         NAME ## Struct ()                                   \
00196             : extMutex( false )                             \
00197             , inRegion( lunchbox::ThreadID::ZERO )          \
00198             {}                                              \
00199         mutable lunchbox::ThreadID id;                      \
00200         mutable std::string name;                           \
00201         bool extMutex;                                      \
00202         mutable lunchbox::ThreadID inRegion;                \
00203     } NAME;                                                 \
00204 private:
00205 
00206 #ifdef LB_CHECK_THREADSAFETY
00207 #  define LB_TS_RESET( NAME ) NAME.id = lunchbox::ThreadID::ZERO;
00208 
00209 #  define LB_TS_THREAD( NAME )                                          \
00210     {                                                                   \
00211         if( NAME.id == lunchbox::ThreadID::ZERO )                       \
00212         {                                                               \
00213             NAME.id = lunchbox::Thread::getSelfThreadID();              \
00214             NAME.name = lunchbox::Log::instance().getThreadName();      \
00215             LBVERB << "Functions for " << #NAME                         \
00216                    << " locked to this thread" << std::endl;            \
00217         }                                                               \
00218         if( !NAME.extMutex && NAME.id != lunchbox::Thread::getSelfThreadID( )) \
00219         {                                                               \
00220             LBERROR << "Threadsafety check for " << #NAME               \
00221                     << " failed on object of type "                     \
00222                     << lunchbox::className( this ) << ", thread "       \
00223                     << lunchbox::Thread::getSelfThreadID() << " ("      \
00224                     << lunchbox::Log::instance().getThreadName() << ") != " \
00225                     << NAME.id << " (" << NAME.name << ")" << std::endl; \
00226             LBABORT( "Non-threadsave code called from two threads" );   \
00227         }                                                               \
00228     }
00229 
00230 #  define LB_TS_NOT_THREAD( NAME )                                      \
00231     {                                                                   \
00232         if( !NAME.extMutex && NAME.id != lunchbox::ThreadID::ZERO )     \
00233         {                                                               \
00234             if( NAME.id == lunchbox::Thread::getSelfThreadID( ))        \
00235             {                                                           \
00236                 LBERROR << "Threadsafety check for not " << #NAME       \
00237                         << " failed on object of type "                 \
00238                         << lunchbox::className( this ) << std::endl;    \
00239                 LBABORT( "Code called from wrong thread" );             \
00240             }                                                           \
00241         }                                                               \
00242     }
00243 
00245     template< typename T > class ScopedThreadCheck : public NonCopyable
00246     {
00247     public:
00248         explicit ScopedThreadCheck( const T& data )
00249                 : _data( data )
00250         {
00251             LBASSERTINFO( data.inRegion == lunchbox::ThreadID::ZERO ||
00252                           data.inRegion == lunchbox::Thread::getSelfThreadID(),
00253                           "Another thread already in critical region" );
00254             data.inRegion = lunchbox::Thread::getSelfThreadID();
00255         }
00256 
00257         ~ScopedThreadCheck()
00258         {
00259             LBASSERTINFO( _data.inRegion == lunchbox::ThreadID::ZERO ||
00260                           _data.inRegion == lunchbox::Thread::getSelfThreadID(),
00261                           "Another thread entered critical region" );
00262             _data.inRegion = lunchbox::ThreadID::ZERO;
00263         }
00264     private:
00265         const T& _data;
00266     };
00269 # define LB_TS_SCOPED( NAME ) \
00270     lunchbox::ScopedThreadCheck< NAME ## Struct > scoped ## NAME ## Check(NAME);
00271 
00272 #else
00273 #  define LB_TS_RESET( NAME ) {}
00274 #  define LB_TS_THREAD( NAME ) {}
00275 #  define LB_TS_NOT_THREAD( NAME ) {}
00276 #  define LB_TS_SCOPED( NAME ) {}
00277 #endif
00278 
00279 }
00280 #endif //LUNCHBOX_THREAD_H
Generated on Tue May 1 2012 15:14:28 for Equalizer 1.3.1-git by  doxygen 1.8.0