Lunchbox  1.17.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
34 {
35 class Thread;
36 }
37 
44 class Thread
45 {
46 public:
48  enum Affinity
49  {
50  NONE = 0,
51  CORE = 1,
52  SOCKET = -65536,
53  SOCKET_MAX = -1024
54  };
55 
57  LUNCHBOX_API Thread();
58 
60  LUNCHBOX_API explicit Thread(const Thread& from);
61 
63  LUNCHBOX_API virtual ~Thread();
64 
73  LUNCHBOX_API virtual bool start();
74 
86  virtual bool init() { return true; }
95  virtual void run() = 0;
96 
105  LUNCHBOX_API virtual void exit();
106 
113  LUNCHBOX_API void cancel();
114 
121  LUNCHBOX_API bool join();
122 
132  LUNCHBOX_API bool isStopped() const;
133 
143  LUNCHBOX_API bool isRunning() const;
144 
150  LUNCHBOX_API bool isCurrent() const;
151 
153  LUNCHBOX_API static ThreadID getSelfThreadID();
154 
156  LUNCHBOX_API static void yield();
157 
159  LUNCHBOX_API static void setName(const std::string& name);
160 
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 
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 
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 
253 template <typename T>
254 class ScopedThreadCheck : public boost::noncopyable
255 {
256 public:
257  explicit ScopedThreadCheck(const T& data)
258  : _data(data)
259  {
260  LBASSERTINFO(data.inRegion == lunchbox::ThreadID() ||
261  data.inRegion == lunchbox::Thread::getSelfThreadID(),
262  "Another thread already in critical region");
263  data.inRegion = lunchbox::Thread::getSelfThreadID();
264  }
265 
266  ~ScopedThreadCheck()
267  {
268  LBASSERTINFO(_data.inRegion == lunchbox::ThreadID() ||
269  _data.inRegion == lunchbox::Thread::getSelfThreadID(),
270  "Another thread entered critical region");
271  _data.inRegion = lunchbox::ThreadID();
272  }
273 
274 private:
275  const T& _data;
276 };
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
static ThreadID getSelfThreadID()
Defines export visibility macros for library Lunchbox.
Basic type definitions not provided by the operating system.
bool exit()
De-initialize the Lunchbox base classes.
Affinity
Enumeration values for thread affinity.
Definition: thread.h:48
Utility class to execute code in a separate execution thread.
Definition: thread.h:44
An utility class to wrap OS-specific thread identifiers.
Definition: threadID.h:35
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:29
std::ostream & operator<<(std::ostream &os, const Array< T > &array)
Pretty-print all members of the array.
Definition: array.h:59
virtual bool init()
The init function for the child thread.
Definition: thread.h:86