Lunchbox  1.12.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
thread.h
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 
41 class Thread
42 {
43 public:
45  enum Affinity
46  {
47  NONE = 0,
48  CORE = 1,
49  SOCKET = -65536,
50  SOCKET_MAX = -1024
51  };
52 
54  LUNCHBOX_API Thread();
55 
57  LUNCHBOX_API explicit Thread( const Thread& from );
58 
60  LUNCHBOX_API virtual ~Thread();
61 
70  LUNCHBOX_API virtual bool start();
71 
83  virtual bool init(){ return true; }
84 
93  virtual void run() = 0;
94 
103  LUNCHBOX_API virtual void exit();
104 
111  LUNCHBOX_API void cancel();
112 
119  LUNCHBOX_API bool join();
120 
130  LUNCHBOX_API bool isStopped() const;
131 
141  LUNCHBOX_API bool isRunning() const;
142 
148  LUNCHBOX_API bool isCurrent() const;
149 
151  LUNCHBOX_API static ThreadID getSelfThreadID();
152 
154  LUNCHBOX_API static void yield();
155 
157  LUNCHBOX_API static void setName( const std::string& name );
158 
169  LUNCHBOX_API static void setAffinity( const int32_t affinity );
170 
171 private:
172  detail::Thread* const _impl;
173 
174  Thread& operator=( const Thread& ) { return *this; }
175 
176  static void* runChild( void* arg );
177  void _runChild();
178 };// LB_DEPRECATED;
179 
181 LUNCHBOX_API std::ostream& operator << ( std::ostream&, const Thread::Affinity );
182 
183 // These thread-safety checks are for development purposes, to check that
184 // certain objects are properly used within the framework. Leaving them enabled
185 // during application development may cause false positives, e.g., when
186 // threadsafety is ensured outside of the objects by the application.
187 
188 #ifndef NDEBUG
189 # define LB_CHECK_THREADSAFETY
190 #endif
191 
193 #define LB_TS_VAR( NAME ) \
194  public: \
195  struct NAME ## Struct \
196  { \
197  NAME ## Struct () \
198  : extMutex( false ) \
199  {} \
200  mutable lunchbox::ThreadID id; \
201  mutable std::string name; \
202  bool extMutex; \
203  mutable lunchbox::ThreadID inRegion; \
204  } NAME; \
205 private:
206 
207 #ifdef LB_CHECK_THREADSAFETY
208 # define LB_TS_RESET( NAME ) NAME.id = lunchbox::ThreadID();
209 
210 # define LB_TS_THREAD( NAME ) \
211  { \
212  if( NAME.id == lunchbox::ThreadID( )) \
213  { \
214  NAME.id = lunchbox::Thread::getSelfThreadID(); \
215  NAME.name = lunchbox::Log::instance().getThreadName(); \
216  LBVERB << "Functions for " << #NAME \
217  << " locked from" << lunchbox::backtrace << std::endl; \
218  } \
219  if( !NAME.extMutex && NAME.id != lunchbox::Thread::getSelfThreadID( )) \
220  { \
221  LBERROR << "Threadsafety check for " << #NAME \
222  << " failed on object of type " \
223  << lunchbox::className( this ) << ", thread " \
224  << lunchbox::Thread::getSelfThreadID() << " (" \
225  << lunchbox::Log::instance().getThreadName() << ") != " \
226  << NAME.id << " (" << NAME.name << ")" << std::endl; \
227  LBABORT( "Non-threadsafe code called from two threads" ); \
228  } \
229  }
230 
231 # define LB_TS_NOT_THREAD( NAME ) \
232  { \
233  if( !NAME.extMutex && NAME.id != lunchbox::ThreadID( )) \
234  { \
235  if( NAME.id == lunchbox::Thread::getSelfThreadID( )) \
236  { \
237  LBERROR << "Threadsafety check for not " << #NAME \
238  << " failed on object of type " \
239  << lunchbox::className( this ) << std::endl; \
240  LBABORT( "Code called from wrong thread" ); \
241  } \
242  } \
243  }
244 
246 template< typename T > class ScopedThreadCheck : public boost::noncopyable
247 {
248 public:
249  explicit ScopedThreadCheck( const T& data )
250  : _data( data )
251  {
252  LBASSERTINFO( data.inRegion == lunchbox::ThreadID() ||
253  data.inRegion == lunchbox::Thread::getSelfThreadID(),
254  "Another thread already in critical region" );
255  data.inRegion = lunchbox::Thread::getSelfThreadID();
256  }
257 
258  ~ScopedThreadCheck()
259  {
260  LBASSERTINFO( _data.inRegion == lunchbox::ThreadID() ||
261  _data.inRegion == lunchbox::Thread::getSelfThreadID(),
262  "Another thread entered critical region" );
263  _data.inRegion = lunchbox::ThreadID();
264  }
265 private:
266  const T& _data;
267 };
270 # define LB_TS_SCOPED( NAME ) \
271  lunchbox::ScopedThreadCheck< NAME ## Struct > scoped ## NAME ## Check(NAME);
272 
273 #else
274 # define LB_TS_RESET( NAME ) {}
275 # define LB_TS_THREAD( NAME ) {}
276 # define LB_TS_NOT_THREAD( NAME ) {}
277 # define LB_TS_SCOPED( NAME ) {}
278 #endif
279 
280 }
281 #endif //LUNCHBOX_THREAD_H
Bind to a specific CPU core.
Definition: thread.h:48
Defines export visibility macros for library Lunchbox.
static LUNCHBOX_API ThreadID getSelfThreadID()
Basic type definitions not provided by the operating system.
Highest bindable CPU.
Definition: thread.h:50
LUNCHBOX_API Thread()
Construct a new thread.
Affinity
Enumeration values for thread affinity.
Definition: thread.h:45
Utility class to execute code in a separate execution thread.
Definition: thread.h:41
virtual LUNCHBOX_API bool start()
Start the thread.
virtual LUNCHBOX_API ~Thread()
Destruct the thread.
An utility class to wrap OS-specific thread identifiers.
Definition: threadID.h:35
Don't set any affinity.
Definition: thread.h:47
Bind to all cores of a specific socket (CPU)
Definition: thread.h:49
LUNCHBOX_API void cancel()
Cancel (stop) the child thread.
LUNCHBOX_API bool isStopped() const
Return if the thread is stopped.
LUNCHBOX_API bool isRunning() const
Return if the thread is running.
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
virtual LUNCHBOX_API void exit()
Exit the child thread immediately.
std::ostream & operator<<(std::ostream &os, const Array< T > &array)
Pretty-print all members of the array.
Definition: array.h:47
virtual bool init()
The init function for the child thread.
Definition: thread.h:83
LUNCHBOX_API bool isCurrent() const
virtual void run()=0
The entry function for the child thread.
LUNCHBOX_API bool join()
Wait for the exit of the child thread.