LCOV - code coverage report
Current view: top level - lunchbox - thread.h (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 10 10 100.0 %
Date: 2018-10-03 05:33:11 Functions: 5 5 100.0 %

          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
      34             : {
      35             : class Thread;
      36             : }
      37             : 
      38             : /**
      39             :  * Utility class to execute code in a separate execution thread.
      40             :  * @deprecated Use Boost.Thread
      41             :  *
      42             :  * Example: @include tests/thread.cpp
      43             :  */
      44             : class Thread
      45             : {
      46             : public:
      47             :     /** Enumeration values for thread affinity. */
      48             :     enum Affinity
      49             :     {
      50             :         NONE = 0,          //!< Don't set any affinity
      51             :         CORE = 1,          //!< Bind to a specific CPU core
      52             :         SOCKET = -65536,   //!< Bind to all cores of a specific socket (CPU)
      53             :         SOCKET_MAX = -1024 //!< Highest bindable CPU
      54             :     };
      55             : 
      56             :     /** Construct a new thread. @version 1.0 */
      57             :     LUNCHBOX_API Thread();
      58             : 
      59             :     /** Copy constructor. @version 1.1.2 */
      60             :     LUNCHBOX_API explicit Thread(const Thread& from);
      61             : 
      62             :     /** Destruct the thread. @version 1.0 */
      63             :     LUNCHBOX_API virtual ~Thread();
      64             : 
      65             :     /**
      66             :      * Start the thread.
      67             :      *
      68             :      * @return true if the thread was launched and initialized successfully,
      69             :      *         false otherwise.
      70             :      * @sa init(), run()
      71             :      * @version 1.0
      72             :      */
      73             :     LUNCHBOX_API virtual bool start();
      74             : 
      75             :     /**
      76             :      * The init function for the child thread.
      77             :      *
      78             :      * The parent thread will not be unlocked before this function has been
      79             :      * executed. If the thread initialization fails, that is, this method does
      80             :      * return false, the thread will be stopped and the start() method will
      81             :      * return false.
      82             :      *
      83             :      * @return the success value of the thread initialization.
      84             :      * @version 1.0
      85             :      */
      86        1406 :     virtual bool init() { return true; }
      87             :     /**
      88             :      * The entry function for the child thread.
      89             :      *
      90             :      * This method should contain the main execution routine for the thread and
      91             :      * is called after a successful init().
      92             :      *
      93             :      * @version 1.0
      94             :      */
      95             :     virtual void run() = 0;
      96             : 
      97             :     /**
      98             :      * Exit the child thread immediately.
      99             :      *
     100             :      * This function does not return. It is only to be called from the child
     101             :      * thread.
     102             :      *
     103             :      * @version 1.0
     104             :      */
     105             :     LUNCHBOX_API virtual void exit();
     106             : 
     107             :     /**
     108             :      * Cancel (stop) the child thread.
     109             :      *
     110             :      * This function is not to be called from the child thread.
     111             :      * @version 1.0
     112             :      */
     113             :     LUNCHBOX_API void cancel();
     114             : 
     115             :     /**
     116             :      * Wait for the exit of the child thread.
     117             :      *
     118             :      * @return true if the thread was joined, false otherwise.
     119             :      * @version 1.0
     120             :      */
     121             :     LUNCHBOX_API bool join();
     122             : 
     123             :     /**
     124             :      * Return if the thread is stopped.
     125             :      *
     126             :      * Note that the thread may be neither running nor stopped if it is
     127             :      * currently starting or stopping.
     128             :      *
     129             :      * @return true if the thread is stopped, false if not.
     130             :      * @version 1.0
     131             :      */
     132             :     LUNCHBOX_API bool isStopped() const;
     133             : 
     134             :     /**
     135             :      * Return if the thread is running.
     136             :      *
     137             :      * Note that the thread may be neither running nor stopped if it is
     138             :      * currently starting or stopping.
     139             :      *
     140             :      * @return true if the thread is running, false if not.
     141             :      * @version 1.0
     142             :      */
     143             :     LUNCHBOX_API bool isRunning() const;
     144             : 
     145             :     /**
     146             :      * @return true if the calling thread is the same thread as this
     147             :      *         thread, false otherwise.
     148             :      * @version 1.0
     149             :      */
     150             :     LUNCHBOX_API bool isCurrent() const;
     151             : 
     152             :     /** @return a unique identifier for the calling thread. @version 1.0 */
     153             :     LUNCHBOX_API static ThreadID getSelfThreadID();
     154             : 
     155             :     /** @internal */
     156             :     LUNCHBOX_API static void yield();
     157             : 
     158             :     /** @internal */
     159             :     LUNCHBOX_API static void setName(const std::string& name);
     160             : 
     161             :     /** @internal
     162             :      * Set the affinity of the calling thread.
     163             :      *
     164             :      * If given a value greater or equal than CORE, this method binds the
     165             :      * calling thread to core affinity - CORE. If set to a value greater than
     166             :      * CPU and smaller than 0, this method binds the calling thread to all cores
     167             :      * of the given processor (affinity - CPU).
     168             :      *
     169             :      * @param affinity the affinity value (see above).
     170             :      */
     171             :     LUNCHBOX_API static void setAffinity(const int32_t affinity);
     172             : 
     173             : private:
     174             :     detail::Thread* const _impl;
     175             : 
     176             :     Thread& operator=(const Thread&) { return *this; }
     177             :     static void* runChild(void* arg);
     178             :     void _runChild();
     179             : 
     180             :     LUNCHBOX_API friend void abort(bool);
     181             :     static void _dumpAll();
     182             : };
     183             : 
     184             : /** Output the affinity setting in human-readable form. @version 1.7.1 */
     185             : LUNCHBOX_API std::ostream& operator<<(std::ostream&, const Thread::Affinity);
     186             : 
     187             : // These thread-safety checks are for development purposes, to check that
     188             : // certain objects are properly used within the framework. Leaving them enabled
     189             : // during application development may cause false positives, e.g., when
     190             : // threadsafety is ensured outside of the objects by the application.
     191             : 
     192             : #ifndef NDEBUG
     193             : #define LB_CHECK_THREADSAFETY
     194             : #endif
     195             : 
     196             : /** Declare a thread id variable to be used for thread-safety checks. */
     197             : #define LB_TS_VAR(NAME)                      \
     198             : public:                                      \
     199             :     struct NAME##Struct                      \
     200             :     {                                        \
     201             :         NAME##Struct()                       \
     202             :             : extMutex(false)                \
     203             :         {                                    \
     204             :         }                                    \
     205             :         mutable lunchbox::ThreadID id;       \
     206             :         mutable std::string name;            \
     207             :         bool extMutex;                       \
     208             :         mutable lunchbox::ThreadID inRegion; \
     209             :     } NAME;                                  \
     210             :                                              \
     211             : private:
     212             : 
     213             : #ifdef LB_CHECK_THREADSAFETY
     214             : #define LB_TS_RESET(NAME) NAME.id = lunchbox::ThreadID();
     215             : 
     216             : #define LB_TS_THREAD(NAME)                                                    \
     217             :     {                                                                         \
     218             :         if (NAME.id == lunchbox::ThreadID())                                  \
     219             :         {                                                                     \
     220             :             NAME.id = lunchbox::Thread::getSelfThreadID();                    \
     221             :             NAME.name = lunchbox::Log::instance().getThreadName();            \
     222             :             LBVERB << "Functions for " << #NAME << " locked from"             \
     223             :                    << lunchbox::backtrace << std::endl;                       \
     224             :         }                                                                     \
     225             :         if (!NAME.extMutex && NAME.id != lunchbox::Thread::getSelfThreadID()) \
     226             :         {                                                                     \
     227             :             LBERROR << "Threadsafety check for " << #NAME                     \
     228             :                     << " failed on object of type "                           \
     229             :                     << lunchbox::className(this) << ", thread "               \
     230             :                     << lunchbox::Thread::getSelfThreadID() << " ("            \
     231             :                     << lunchbox::Log::instance().getThreadName()              \
     232             :                     << ") != " << NAME.id << " (" << NAME.name << ")"         \
     233             :                     << std::endl;                                             \
     234             :             LBABORT("Non-threadsafe code called from two threads");           \
     235             :         }                                                                     \
     236             :     }
     237             : 
     238             : #define LB_TS_NOT_THREAD(NAME)                                     \
     239             :     {                                                              \
     240             :         if (!NAME.extMutex && NAME.id != lunchbox::ThreadID())     \
     241             :         {                                                          \
     242             :             if (NAME.id == lunchbox::Thread::getSelfThreadID())    \
     243             :             {                                                      \
     244             :                 LBERROR << "Threadsafety check for not " << #NAME  \
     245             :                         << " failed on object of type "            \
     246             :                         << lunchbox::className(this) << std::endl; \
     247             :                 LBABORT("Code called from wrong thread");          \
     248             :             }                                                      \
     249             :         }                                                          \
     250             :     }
     251             : 
     252             : /** @cond IGNORE */
     253             : template <typename T>
     254             : class ScopedThreadCheck : public boost::noncopyable
     255             : {
     256             : public:
     257     1078328 :     explicit ScopedThreadCheck(const T& data)
     258     1078328 :         : _data(data)
     259             :     {
     260     1078328 :         LBASSERTINFO(data.inRegion == lunchbox::ThreadID() ||
     261             :                          data.inRegion == lunchbox::Thread::getSelfThreadID(),
     262             :                      "Another thread already in critical region");
     263     1078328 :         data.inRegion = lunchbox::Thread::getSelfThreadID();
     264     1078328 :     }
     265             : 
     266     1078328 :     ~ScopedThreadCheck()
     267             :     {
     268     1078328 :         LBASSERTINFO(_data.inRegion == lunchbox::ThreadID() ||
     269             :                          _data.inRegion == lunchbox::Thread::getSelfThreadID(),
     270             :                      "Another thread entered critical region");
     271     1078328 :         _data.inRegion = lunchbox::ThreadID();
     272     1078328 :     }
     273             : 
     274             : private:
     275             :     const T& _data;
     276             : };
     277             : /** @endcond */
     278             : 
     279             : #define LB_TS_SCOPED(NAME) \
     280             :     lunchbox::ScopedThreadCheck<NAME##Struct> scoped##NAME##Check(NAME);
     281             : 
     282             : #else
     283             : #define LB_TS_RESET(NAME) \
     284             :     {                     \
     285             :     }
     286             : #define LB_TS_THREAD(NAME) \
     287             :     {                      \
     288             :     }
     289             : #define LB_TS_NOT_THREAD(NAME) \
     290             :     {                          \
     291             :     }
     292             : #define LB_TS_SCOPED(NAME) \
     293             :     {                      \
     294             :     }
     295             : #endif
     296             : }
     297             : #endif // LUNCHBOX_THREAD_H

Generated by: LCOV version 1.11