LCOV - code coverage report
Current view: top level - lunchbox - thread.h (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 10 10 100.0 %
Date: 2014-08-05 Functions: 9 13 69.2 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *               2012, Marwan Abdellah <marwan.abdellah@epfl.ch>
       4             :  *               2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #ifndef LUNCHBOX_THREAD_H
      21             : #define LUNCHBOX_THREAD_H
      22             : 
      23             : #include <lunchbox/api.h>         // LUNCHBOX_API definition
      24             : #include <lunchbox/debug.h>       // debug macros in thread-safety checks
      25             : #include <lunchbox/threadID.h>    // member
      26             : #include <lunchbox/types.h>
      27             : 
      28             : #include <boost/noncopyable.hpp>
      29             : #include <ostream>
      30             : 
      31             : namespace lunchbox
      32             : {
      33             : namespace detail { class Thread; }
      34             : 
      35             : /**
      36             :  * Utility class to execute code in a separate execution thread.
      37             :  * @deprecated Use Boost.Thread
      38             :  *
      39             :  * Example: @include tests/thread.cpp
      40             :  */
      41             : class Thread
      42             : {
      43             : public:
      44             :     /** Enumeration values for thread affinity. */
      45             :     enum Affinity
      46             :     {
      47             :         NONE = 0, //!< Don't set any affinity
      48             :         CORE = 1, //!< Bind to a specific CPU core
      49             :         SOCKET = -65536, //!< Bind to all cores of a specific socket (CPU)
      50             :         SOCKET_MAX = -1024 //!< Highest bindable CPU
      51             :     };
      52             : 
      53             :     /** Construct a new thread. @version 1.0 */
      54             :     LUNCHBOX_API Thread();
      55             : 
      56             :     /** Copy constructor. @version 1.1.2 */
      57             :     LUNCHBOX_API Thread( const Thread& from );
      58             : 
      59             :     /** Destruct the thread. @version 1.0 */
      60             :     LUNCHBOX_API virtual ~Thread();
      61             : 
      62             :     /**
      63             :      * Start the thread.
      64             :      *
      65             :      * @return true if the thread was launched and initialized successfully,
      66             :      *         false otherwise.
      67             :      * @sa init(), run()
      68             :      * @version 1.0
      69             :      */
      70             :     LUNCHBOX_API virtual bool start();
      71             : 
      72             :     /**
      73             :      * The init function for the child thread.
      74             :      *
      75             :      * The parent thread will not be unlocked before this function has been
      76             :      * executed. If the thread initialization fails, that is, this method does
      77             :      * return false, the thread will be stopped and the start() method will
      78             :      * return false.
      79             :      *
      80             :      * @return the success value of the thread initialization.
      81             :      * @version 1.0
      82             :      */
      83        3238 :     virtual bool init(){ return true; }
      84             : 
      85             :     /**
      86             :      * The entry function for the child thread.
      87             :      *
      88             :      * This method should contain the main execution routine for the thread and
      89             :      * is called after a successful init().
      90             :      *
      91             :      * @version 1.0
      92             :      */
      93             :     virtual void run() = 0;
      94             : 
      95             :     /**
      96             :      * Exit the child thread immediately.
      97             :      *
      98             :      * This function does not return. It is only to be called from the child
      99             :      * thread.
     100             :      *
     101             :      * @version 1.0
     102             :      */
     103             :     LUNCHBOX_API virtual void exit();
     104             : 
     105             :     /**
     106             :      * Cancel (stop) the child thread.
     107             :      *
     108             :      * This function is not to be called from the child thread.
     109             :      * @version 1.0
     110             :      */
     111             :     LUNCHBOX_API void cancel();
     112             : 
     113             :     /**
     114             :      * Wait for the exit of the child thread.
     115             :      *
     116             :      * @return true if the thread was joined, false otherwise.
     117             :      * @version 1.0
     118             :      */
     119             :     LUNCHBOX_API bool join();
     120             : 
     121             :     /**
     122             :      * Return if the thread is stopped.
     123             :      *
     124             :      * Note that the thread may be neither running nor stopped if it is
     125             :      * currently starting or stopping.
     126             :      *
     127             :      * @return true if the thread is stopped, false if not.
     128             :      * @version 1.0
     129             :      */
     130             :     LUNCHBOX_API bool isStopped() const;
     131             : 
     132             :     /**
     133             :      * Return if the thread is running.
     134             :      *
     135             :      * Note that the thread may be neither running nor stopped if it is
     136             :      * currently starting or stopping.
     137             :      *
     138             :      * @return true if the thread is running, false if not.
     139             :      * @version 1.0
     140             :      */
     141             :     LUNCHBOX_API bool isRunning() const;
     142             : 
     143             :     /**
     144             :      * @return true if the calling thread is the same thread as this
     145             :      *         thread, false otherwise.
     146             :      * @version 1.0
     147             :      */
     148             :     LUNCHBOX_API bool isCurrent() const;
     149             : 
     150             :     /** @return a unique identifier for the calling thread. @version 1.0 */
     151             :     LUNCHBOX_API static ThreadID getSelfThreadID();
     152             : 
     153             :     /** @internal */
     154             :     LUNCHBOX_API static void yield();
     155             : 
     156             :     /** @internal */
     157             :     static void pinCurrentThread();
     158             : 
     159             :     /** @internal */
     160             :     LUNCHBOX_API static void setName( const std::string& name );
     161             : 
     162             :     /** @internal
     163             :      * Set the affinity of the calling thread.
     164             :      *
     165             :      * If given a value greater or equal than CORE, this method binds the
     166             :      * calling thread to core affinity - CORE. If set to a value greater than
     167             :      * CPU and smaller than 0, this method binds the calling thread to all cores
     168             :      * of the given processor (affinity - CPU).
     169             :      *
     170             :      * @param affinity the affinity value (see above).
     171             :      */
     172             :     LUNCHBOX_API static void setAffinity( const int32_t affinity );
     173             : 
     174             : private:
     175             :     detail::Thread* const _impl;
     176             : 
     177             :     Thread& operator=( const Thread& ) { return *this; }
     178             : 
     179             :     static void* runChild( void* arg );
     180             :     void        _runChild();
     181             : };// LB_DEPRECATED;
     182             : 
     183             : /** Output the affinity setting in human-readable form. @version 1.7.1 */
     184             : LUNCHBOX_API std::ostream& operator << ( std::ostream&, const Thread::Affinity );
     185             : 
     186             : // These thread-safety checks are for development purposes, to check that
     187             : // certain objects are properly used within the framework. Leaving them enabled
     188             : // during application development may cause false positives, e.g., when
     189             : // threadsafety is ensured outside of the objects by the application.
     190             : 
     191             : #ifndef NDEBUG
     192             : #  define LB_CHECK_THREADSAFETY
     193             : #endif
     194             : 
     195             : /** Declare a thread id variable to be used for thread-safety checks. */
     196             : #define LB_TS_VAR( NAME )                       \
     197             :     public:                                     \
     198             :     struct NAME ## Struct                       \
     199             :     {                                           \
     200             :         NAME ## Struct ()                       \
     201             :             : extMutex( false )                 \
     202             :         {}                                      \
     203             :         mutable lunchbox::ThreadID id;          \
     204             :         mutable std::string name;               \
     205             :         bool extMutex;                          \
     206             :         mutable lunchbox::ThreadID inRegion;    \
     207             :     } NAME;                                     \
     208             : private:
     209             : 
     210             : #ifdef LB_CHECK_THREADSAFETY
     211             : #  define LB_TS_RESET( NAME ) NAME.id = lunchbox::ThreadID();
     212             : 
     213             : #  define LB_TS_THREAD( NAME )                                          \
     214             :     {                                                                   \
     215             :         if( NAME.id == lunchbox::ThreadID( ))                           \
     216             :         {                                                               \
     217             :             NAME.id = lunchbox::Thread::getSelfThreadID();              \
     218             :             NAME.name = lunchbox::Log::instance().getThreadName();      \
     219             :             LBVERB << "Functions for " << #NAME                         \
     220             :                    << " locked from" << lunchbox::backtrace <<  std::endl; \
     221             :         }                                                               \
     222             :         if( !NAME.extMutex && NAME.id != lunchbox::Thread::getSelfThreadID( )) \
     223             :         {                                                               \
     224             :             LBERROR << "Threadsafety check for " << #NAME               \
     225             :                     << " failed on object of type "                     \
     226             :                     << lunchbox::className( this ) << ", thread "       \
     227             :                     << lunchbox::Thread::getSelfThreadID() << " ("      \
     228             :                     << lunchbox::Log::instance().getThreadName() << ") != " \
     229             :                     << NAME.id << " (" << NAME.name << ")" << std::endl; \
     230             :             LBABORT( "Non-threadsafe code called from two threads" );   \
     231             :         }                                                               \
     232             :     }
     233             : 
     234             : #  define LB_TS_NOT_THREAD( NAME )                                      \
     235             :     {                                                                   \
     236             :         if( !NAME.extMutex && NAME.id != lunchbox::ThreadID( ))         \
     237             :         {                                                               \
     238             :             if( NAME.id == lunchbox::Thread::getSelfThreadID( ))        \
     239             :             {                                                           \
     240             :                 LBERROR << "Threadsafety check for not " << #NAME       \
     241             :                         << " failed on object of type "                 \
     242             :                         << lunchbox::className( this ) << std::endl;    \
     243             :                 LBABORT( "Code called from wrong thread" );             \
     244             :             }                                                           \
     245             :         }                                                               \
     246             :     }
     247             : 
     248             : /** @cond IGNORE */
     249             : template< typename T > class ScopedThreadCheck : public boost::noncopyable
     250             : {
     251             : public:
     252     1618197 :     explicit ScopedThreadCheck( const T& data )
     253     1618197 :         : _data( data )
     254             :     {
     255     1618197 :         LBASSERTINFO( data.inRegion == lunchbox::ThreadID() ||
     256             :                       data.inRegion == lunchbox::Thread::getSelfThreadID(),
     257             :                       "Another thread already in critical region" );
     258     1618197 :         data.inRegion = lunchbox::Thread::getSelfThreadID();
     259     1618197 :     }
     260             : 
     261     1618197 :     ~ScopedThreadCheck()
     262             :     {
     263     1618197 :         LBASSERTINFO( _data.inRegion == lunchbox::ThreadID() ||
     264             :                       _data.inRegion == lunchbox::Thread::getSelfThreadID(),
     265             :                       "Another thread entered critical region" );
     266     1618197 :         _data.inRegion = lunchbox::ThreadID();
     267     1618197 :     }
     268             : private:
     269             :     const T& _data;
     270             : };
     271             : /** @endcond */
     272             : 
     273             : # define LB_TS_SCOPED( NAME )                                           \
     274             :     lunchbox::ScopedThreadCheck< NAME ## Struct > scoped ## NAME ## Check(NAME);
     275             : 
     276             : #else
     277             : #  define LB_TS_RESET( NAME ) {}
     278             : #  define LB_TS_THREAD( NAME ) {}
     279             : #  define LB_TS_NOT_THREAD( NAME ) {}
     280             : #  define LB_TS_SCOPED( NAME ) {}
     281             : #endif
     282             : 
     283             : }
     284             : #endif //LUNCHBOX_THREAD_H

Generated by: LCOV version 1.10