Evo C++ Library v0.5.1
thread.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_thread_h
9 #define INCL_evo_thread_h
10 
11 #include "impl/systhread.h"
12 #include "thread_inert.h"
13 #include "atomic.h"
14 #include "lock.h"
15 #include "type.h"
16 #if defined(EVO_CPP11)
17  #include <functional>
18 #endif
19 
21 
22 // Disable certain MSVC warnings for this file, if !EVO_CPP11
23 #if defined(_MSC_VER) && !defined(EVO_CPP11)
24  #pragma warning(push)
25  #pragma warning(disable:4355)
26 #endif
27 
28 namespace evo {
33 
35 
41 inline ulong get_tid()
42  { return SysThread::id(); }
43 
45 
54 struct SpinLock : public AtomicFlag {
57 
60  { }
61 
62 private:
63  // Disable copying
65  SpinLock& operator=(SpinLock&);
66 };
67 
69 
76 struct SleepLock : public SpinLock {
78 
81  { }
82 
83 private:
84  // Disable copying
86  SleepLock& operator=(SleepLock&);
87 
88  // Disable sleepless spin-lock
89  using SpinLock::lock;
90 };
91 
93 
104 struct Mutex : public SysMutex {
106 
109  { }
110 
111 private:
112  // Disable copying
113  Mutex(const Mutex&);
114  Mutex& operator=(const Mutex&);
115 };
116 
118 
132 struct MutexRW {
136 
139  { counter_ = 0; }
140 
143  assert( counter_ == 0 ); // shouldn't be any read locks
144  }
145 
153  bool trylock()
154  { return write_mutex_.trylock(); }
155 
166  bool trylock(ulong timeout_ms)
167  { return write_mutex_.trylock(timeout_ms); }
168 
173  void lock()
174  { write_mutex_.lock(); }
175 
179  void unlock()
180  { write_mutex_.unlock(); }
181 
189  bool trylock_read() {
190  bool result = false;
191  if (read_mutex_.trylock()) {
192  if (counter_ > 0 || write_mutex_.trylock()) {
193  result = true;
194  ++counter_;
195  assert(counter_ > 0);
196  }
197  read_mutex_.unlock();
198  }
199  return result;
200  }
201 
206  void lock_read() {
207  read_mutex_.lock();
208  if (++counter_ == 1)
209  write_mutex_.lock();
210  assert(counter_ > 0);
211  read_mutex_.unlock();
212  }
213 
217  void unlock_read() {
218  read_mutex_.lock();
219  assert(counter_ > 0);
220  if (--counter_ == 0)
221  write_mutex_.unlock();
222  read_mutex_.unlock();
223  }
224 
225 private:
226  ulong counter_;
227  Mutex read_mutex_;
228  Mutex write_mutex_;
229 };
230 
232 
243 struct Condition {
245 
246 #if defined(_WIN32)
247  // Windows
248  typedef CONDITION_VARIABLE Handle;
249 
250  static const ulong INF = INFINITE;
251 
252  Condition() {
253  InitializeConditionVariable(&handle);
254  owned = false;
255  mutex = new Mutex;
256  owned = true;
257  }
258 
259  Condition(Mutex& mutex) : mutex(&mutex), owned(false)
260  { InitializeConditionVariable(&handle); }
261 
262  bool wait(ulong timeout_ms=Condition::INF, bool locked=true) {
263  if (!locked) {
264  if (timeout_ms >= Condition::INF)
265  mutex->lock();
266  else
267  mutex->trylock(timeout_ms);
268  }
269  return (SleepConditionVariableCS(&handle, &mutex->handle, timeout_ms) != 0);
270  }
271 
272  void notify()
273  { WakeConditionVariable(&handle); }
274 
275  void notify_all()
276  { WakeAllConditionVariable(&handle); }
277 
278 #else
279  // Linux/Unix
280  typedef pthread_cond_t Handle;
281 
282  static const ulong INF = ULONG_MAX;
283 
288  init();
289  owned = false;
290  mutex = new Mutex;
291  owned = true;
292  }
293 
300  Condition(Mutex& mutex) : mutex(&mutex), owned(false) {
301  init();
302  }
303 
317  bool wait(ulong timeout_ms=Condition::INF, bool locked=true) {
318  if (timeout_ms >= Condition::INF) {
319  if (!locked)
320  mutex->lock();
321  return (pthread_cond_wait(&handle, &mutex->handle) == 0);
322  } else {
323  if (!locked)
324  mutex->trylock(timeout_ms);
325  // Clock choice should be consistent with init() below
326  struct timespec ts;
327  #if defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME) && !defined(EVO_USE_GETTIMEOFDAY)
328  #if defined(CLOCK_MONOTONIC) && !defined(__APPLE__)
329  ::clock_gettime(CLOCK_MONOTONIC, &ts);
330  #else
331  ::clock_gettime(CLOCK_REALTIME, &ts);
332  #endif
333  #else
334  {
335  struct timeval tv;
336  ::gettimeofday(&tv, NULL);
338  }
339  #endif
340  SysLinux::add_timespec_ms(ts, timeout_ms);
341  return (pthread_cond_timedwait(&handle, &mutex->handle, &ts) == 0);
342  }
343  }
344 
349  void notify()
350  { pthread_cond_signal(&handle); }
351 
356  void notify_all()
357  { pthread_cond_broadcast(&handle); }
358 
359 private:
360  void init() {
361  // Clock choice should be consistent with wait() above
362  #if defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME) && !defined(EVO_USE_GETTIMEOFDAY) && !defined(__APPLE__)
363  clockid_t id;
364  #if defined(CLOCK_MONOTONIC)
365  id = CLOCK_MONOTONIC;
366  #else
367  id = CLOCK_REALTIME;
368  #endif
369  pthread_condattr_t attr;
370  pthread_condattr_init(&attr);
371  pthread_condattr_setclock(&attr, id);
372  pthread_cond_init(&handle, &attr);
373  #else
374  pthread_cond_init(&handle, NULL);
375  #endif
376  }
377 
378 public:
379 #endif
380 
383  if (owned)
384  delete mutex;
385  }
386 
394  bool wait_inf(bool locked=true) {
395  bool result = wait(Condition::INF, locked);
396  assert( result ); // should never timeout
397  return result;
398  }
399 
406  bool trylock()
407  { return mutex->trylock(); }
408 
418  bool trylock(ulong timeout_ms)
419  { return mutex->trylock(timeout_ms); }
420 
425  void lock()
426  { mutex->lock(); }
427 
431  void unlock()
432  { mutex->unlock(); }
433 
438  bool lock_wait(ulong timeout_ms=Condition::INF) {
439  const bool result = wait(timeout_ms, false);
440  mutex->unlock();
441  return result;
442  }
443 
447  void lock_notify() {
448  mutex->lock();
449  notify();
450  mutex->unlock();
451  }
452 
457  mutex->lock();
458  notify_all();
459  mutex->unlock();
460  }
461 
462  Handle handle;
464  bool owned;
465 
466 private:
467  // Disable copying
468  Condition(const Condition&);
469  Condition& operator=(const Condition&);
470 };
471 
473 
474 // Implementation helpers for Thread
476 namespace impl {
477  // Basic smart pointer used internally without depending on ptr.h
478  template<class T> struct BasicSmartPtr {
479  T* ptr;
480 
481  BasicSmartPtr(T* ptr=NULL) : ptr(ptr)
482  { }
483 
484  ~BasicSmartPtr() {
485  if (ptr != NULL)
486  delete ptr;
487  }
488 
489  private:
490  // Disable copying
491  BasicSmartPtr(const BasicSmartPtr&);
492  BasicSmartPtr& operator=(const BasicSmartPtr&);
493  };
494 }
529 struct Thread {
530 #if defined(EVO_CPP11)
531  typedef std::function<void (void*)> Func;
532 #else
533  typedef void (*Func)(void*);
534 #endif
535 
537  struct Init {
538  Func func;
539  void* arg;
540 
541  Init() : func(NULL), arg(NULL)
542  { }
543 
544  Init(Func func, void* arg=NULL) : func(func), arg(arg)
545  { }
546 
547  Init(const Init& src) : func(src.func), arg(src.arg)
548  { }
549  };
550 
552 
554  Thread() : thread_active_(false)
555  { }
556 
561  Thread(Func func, void* arg=NULL) : thread_init(func, arg), thread_active_(false)
562  { }
563 
567  Thread(const Init& init) : thread_init(init), thread_active_(false)
568  { }
569 
574  virtual ~Thread()
575  { thread_join(); }
576 
581  { return thread_impl_.handle; }
582 
588  bool thread_active() const
589  { return thread_active_; }
590 
596  bool thread_start() {
597  if (!thread_active_ && thread_init.func != NULL) {
598  impl::BasicSmartPtr<Init> init(new Init(thread_init));
599  if (thread_impl_.start(Thread::thread_handler, init.ptr) == ENone) {
600  // init.ptr freed by thread
601  init.ptr = NULL;
602  thread_active_ = true;
603  return true;
604  }
605  }
606  return false;
607  }
608 
613  virtual bool thread_detach() {
614  if (thread_active_) {
615  thread_impl_.detach();
616  thread_active_ = false;
617  }
618  return true;
619  }
620 
626  bool thread_join() {
627  if (thread_active_ && thread_impl_.join()) {
628  thread_active_ = false;
629  return true;
630  }
631  return false;
632  }
633 
635  static void yield()
636  { SysThread::yield(); }
637 
641  static ulong id()
642  { return SysThread::id(); }
643 
644 protected:
647 
648 private:
649  // Platform-specific handler
650  static EVO_THREAD_RUN_DEFINE(thread_handler, ptr) {
651  assert(ptr != NULL);
652  Thread::Init* init_ptr = (Thread::Init*)ptr;
653  if (init_ptr != NULL) {
654  Thread::Init init(*init_ptr);
655  delete init_ptr;
656  if (init.func != NULL)
657  init.func(init.arg);
658  }
660  }
661 };
662 
664 
706 struct ThreadClass : public Thread {
708 
710  ThreadClass() : Thread(ThreadClass::thread_base_handler, this)
711  { }
712 
717  virtual ~ThreadClass() {
718  if (thread_active_)
719  abort(); // Thread must be stopped/joined first!
720  }
721 
730  ThreadClass& thread_cancel(bool locked=false) {
731  if (thread_active_)
732  thread_cancel_flag_.store(1);
733  if (!locked)
734  condmutex.lock();
735  condmutex.notify_all();
736  condmutex.unlock();
737  return *this;
738  }
739 
747  bool thread_cancel_join(bool locked=false)
748  { return thread_cancel(locked).thread_join(); }
749 
756  virtual void thread_run() = 0;
757 
764  bool cancel_check() {
766  return (thread_cancel_flag_.load() != 0);
767  }
768 
769 private:
770  AtomicInt thread_cancel_flag_;
771 
772  // Disable copying
773  ThreadClass(const ThreadClass&);
774  ThreadClass& operator=(const ThreadClass&);
775 
776  // Disable access to: thread_init, thread_detach
777  using Thread::thread_init;
778  bool thread_detach()
779  { return false; }
780 
781  // Thread handler
782  static void thread_base_handler(void* ptr)
783  { ((ThreadClass*)ptr)->thread_run(); }
784 };
785 
787 
825 template<class T=Thread>
826 struct ThreadScope : public T {
828 
831  { this->thread_start(); }
832 
835  { cancel_join(); }
836 
841  { return this->thread_handle(); }
842 
846  bool active() const
847  { return this->thread_active(); }
848 
854  bool start()
855  { return this->thread_start(); }
856 
865  This& cancel(bool locked=false)
866  { this->thread_cancel(locked); return *this; }
867 
874  bool cancel_join(bool locked=false)
875  { return this->thread_cancel(locked).thread_join(); }
876 
882  bool join()
883  { return this->thread_join(); }
884 
885 private:
886  ThreadScope(const ThreadScope&);
887  ThreadScope& operator=(const ThreadScope&);
888 };
889 
923 template<>
924 struct ThreadScope<Thread> : public Thread {
926 
931  ThreadScope(Thread::Func func, void* arg=NULL) : Thread(func, arg)
932  { this->thread_start(); }
933 
936  { this->thread_join(); }
937 
942  { return this->thread_handle(); }
943 
947  bool active() const
948  { return this->thread_active(); }
949 
955  bool start()
956  { return this->thread_start(); }
957 
961  bool join()
962  { return this->thread_join(); }
963 
968  bool detach()
969  { return this->thread_detach(); }
970 
971 private:
972  ThreadScope();
973  ThreadScope(const ThreadScope&);
974  ThreadScope& operator=(const ThreadScope&);
975 };
976 
978 
979 // Implementation helpers for ThreadGroup
981 namespace impl {
982  // Class-based thread node (derives from ThreadClass)
983  template<class S, class T>
984  struct ThreadGroupNode {
985  typedef ThreadGroupNode<S,T> Node;
986  static const bool THREAD_CLASS = true;
987 
988  T thread;
989  Node* next;
990  Node* prev;
991  bool used;
992 
993  ThreadGroupNode(Thread::Init&, S& state, Node* prev_node=NULL) : thread(state) {
994  next = NULL;
995  prev = prev_node;
996  used = false;
997  }
998 
999  void cancel()
1000  { thread.thread_cancel(); }
1001  };
1002 
1003  // Function-based thread node (specialize on Thread)
1004  template<class S>
1005  struct ThreadGroupNode<S,Thread> {
1006  typedef ThreadGroupNode<S,Thread> Node;
1007  static const bool THREAD_CLASS = false;
1008 
1009  Thread thread;
1010  Node* next;
1011  Node* prev;
1012  bool used;
1013 
1014  ThreadGroupNode(Thread::Init& init, S& state, Node* prev_node=NULL) : thread(init) {
1015  next = NULL;
1016  prev = prev_node;
1017  used = false;
1018  thread.thread_init.arg = &state;
1019  }
1020 
1021  void cancel()
1022  { }
1023  };
1024 }
1103 template<class T, class S=typename T::SharedState, class M=MutexInert>
1104 struct ThreadGroup {
1106  typedef typename Thread::Init ThreadInit;
1107  typedef S SharedState;
1108  typedef M MutexT;
1109 
1112  size_ = 0;
1113  first_ = last_ = NULL;
1114  active_ = false;
1115  cancel_flag_ = false;
1116  }
1117 
1121  ThreadGroup(Thread::Func func) : thread_init(func) {
1122  size_ = 0;
1123  first_ = last_ = NULL;
1124  active_ = false;
1125  cancel_flag_ = false;
1126  }
1127 
1131  virtual ~ThreadGroup() {
1132  cancel();
1133  join();
1134  }
1135 
1142  bool active() const
1143  { typename MutexT::Lock lock(mutex_); return active_; }
1144 
1151  bool cancelled() const
1152  { typename MutexT::Lock lock(mutex_); return cancel_flag_; }
1153 
1157  ulong size() const
1158  { typename MutexT::Lock lock(mutex_); return size_; }
1159 
1168  bool start(uint count=1) {
1169  typename MutexT::Lock lock(mutex_);
1170  if (count > 0 && !cancel_flag_ && (Node::THREAD_CLASS || thread_init.func != NULL)) {
1171  active_ = true;
1172  if (first_ == NULL) {
1173  first_ = last_ = new Node(thread_init, shared_state);
1174  last_->thread.thread_start();
1175  ++size_;
1176  --count;
1177  }
1178 
1179  while (count > 0) {
1180  last_->next = new Node(thread_init, shared_state, last_);
1181  last_ = last_->next;
1182  last_->thread.thread_start();
1183  ++size_;
1184  --count;
1185  }
1186  return true;
1187  }
1188  return false;
1189  }
1190 
1196  This& cancel() {
1197  typename MutexT::Lock lock(mutex_);
1198  if (Node::THREAD_CLASS && active_ && !cancel_flag_) {
1199  cancel_flag_ = true;
1200  Node* node = first_;
1201  while (node != NULL) {
1202  node->cancel();
1203  node = node->next;
1204  }
1205  }
1206  return *this;
1207  }
1208 
1212  bool join() {
1213  typename MutexT::Lock lock(mutex_);
1214  if (active_) {
1215  Node* node = first_;
1216  while (node != NULL) {
1217  Node* next = node->next;
1218  node->cancel();
1219  node->thread.thread_join();
1220  delete node;
1221  node = next;
1222  }
1223  size_ = 0;
1224  first_ = last_ = NULL;
1225  cancel_flag_ = false;
1226  active_ = false;
1227  }
1228  return true;
1229  }
1230 
1231  SharedState shared_state;
1232  ThreadInit thread_init;
1233 
1234 protected:
1235  typedef impl::ThreadGroupNode<S,T> Node;
1236 
1237  ulong size_;
1238  Node* first_;
1239  Node* last_;
1240  bool active_;
1242  mutable MutexT mutex_;
1243 
1244 private:
1245  // Disable copying
1246  ThreadGroup(const This&);
1247  This& operator=(const This&);
1248 };
1249 
1251 
1252 #if EVO_ATOMIC_SAFE_STATICS == 1 || defined(DOXYGEN)
1253 
1260 template<class T>
1261 struct Singleton {
1265  static T* instance() {
1266  static Mutex mutex;
1267  static AtomicSmartPtr static_ptr;
1268  T* p = static_ptr.load(EVO_ATOMIC_CONSUME);
1269  if (p == NULL) {
1270  Mutex::Lock lock(mutex);
1271  p = static_ptr.load(EVO_ATOMIC_RELAXED);
1272  if (p == NULL) {
1273  p = new T;
1274  static_ptr.store(p, EVO_ATOMIC_RELEASE);
1275  }
1276  }
1277  return p;
1278  }
1279 
1280 private:
1281  struct AtomicSmartPtr : public Atomic<T*> {
1282  AtomicSmartPtr()
1283  { }
1284 
1285  ~AtomicSmartPtr() {
1286  T* ptr = this->load();
1287  if (ptr != NULL)
1288  delete ptr;
1289  }
1290  };
1291 };
1292 #endif
1293 
1295 
1296 }
1297 #if defined(_MSC_VER) && !defined(EVO_CPP11)
1298  #pragma warning(pop)
1299 #endif
1300 #endif
SleepLock()
Constructor.
Definition: thread.h:80
~ThreadScope()
Destructor cancels and joins thread.
Definition: thread.h:834
bool thread_active() const
Get whether thread is active (running).
Definition: thread.h:588
ThreadScope< T > This
Current ThreadScope.
Definition: thread.h:827
Evo smart locks for synchronization.
Atomic signalling flag.
Definition: atomic.h:172
S SharedState
Thread shared state
Definition: thread.h:1107
MutexRW()
Constructor.
Definition: thread.h:138
static void yield()
Yield control to another thread or process.
Definition: thread.h:635
Func func
Thread function to use
Definition: thread.h:538
virtual ~Thread()
Destructor.
Definition: thread.h:574
bool start()
Start thread.
Definition: thread.h:854
M MutexT
Mutex type
Definition: thread.h:1108
SmartLock< Mutex > Lock
Lock object type – see SmartLock.
Definition: thread.h:105
Smart sleep-locking for synchronization.
Definition: lock.h:146
static ulong id()
Definition: systhread.h:139
Node * first_
Definition: thread.h:1238
Definition: systhread.h:165
void lock_notify()
Lock associated mutex, call notify(), then unlock.
Definition: thread.h:447
void unlock()
Write-Unlock mutex.
Definition: thread.h:179
This & cancel()
Set cancel flags to signal all threads to stop.
Definition: thread.h:1196
#define EVO_THREAD_RUN_DEFINE(NAME, PARAM_NAME)
Used to define a thread run function used with SysThread (used internally).
Definition: systhread.h:40
Manages a single thread of execution.
Definition: thread.h:529
SysThread::Handle handle() const
Get platform-specific thread handle.
Definition: thread.h:840
virtual ~ThreadClass()
Destructor.
Definition: thread.h:717
bool wait_inf(bool locked=true)
Wait for notification.
Definition: thread.h:394
bool trylock(ulong timeout_ms)
Try to Write-Lock mutex with a timeout.
Definition: thread.h:166
~Condition()
Destructor.
Definition: thread.h:382
Mutex * mutex
Pointer to associated mutex, never NULL – do not modify.
Definition: thread.h:463
bool active_
Definition: thread.h:1240
bool start()
Start thread.
Definition: thread.h:955
Read/Write Mutex for thread synchronization.
Definition: thread.h:132
ThreadScope(Thread::Func func, void *arg=NULL)
Constructor starts thread.
Definition: thread.h:931
bool active() const
Get whether thread group is active (threads running).
Definition: thread.h:1142
Handle handle
Condition object handle – do not modify.
Definition: thread.h:462
bool wait(ulong timeout_ms=Condition::INF, bool locked=true)
Wait for notification or timeout.
Definition: thread.h:317
Handle handle
Mutex handle – do not modify.
Definition: systhread.h:293
~MutexRW()
Destructor.
Definition: thread.h:142
Condition object for thread synchronization.
Definition: thread.h:243
Init(const Init &src)
Definition: thread.h:547
ThreadClass()
Constructor.
Definition: thread.h:710
bool cancel_check()
Check if thread has been cancelled.
Definition: thread.h:764
Evo system threads implementation.
Mutex for thread synchronization.
Definition: thread.h:104
Thread()
Constructor.
Definition: thread.h:554
SmartSleepLock< AtomicFlag > Lock
Sleep-Lock object type – see SmartSleepLock.
Definition: thread.h:77
#define EVO_THREAD_RUN_RETURN
Used to return from a thread run function used with SysThread (used internally).
Definition: systhread.h:45
ThreadGroup()
Default constructor.
Definition: thread.h:1111
#define EVO_ATOMIC_RELAXED
Relaxed memory ordering, used between start/end memory barriers.
Definition: atomic.h:21
SysThread::Handle handle() const
Get platform-specific thread handle.
Definition: thread.h:941
Condition condmutex
Condition and mutex object for thread, used to wake up thread.
Definition: thread.h:707
No error.
Definition: sys.h:1115
Evo inert synchronization implementation.
bool detach()
Detach thread to run in background.
Definition: thread.h:968
Creates a single thread of execution in given scope.
Definition: thread.h:826
SmartLock< AtomicFlag > Lock
Lock object type – see SmartLock.
Definition: thread.h:55
bool join()
Join thread by waiting for thread to stop.
Definition: thread.h:882
ThreadGroup< T, S, M > This
This type.
Definition: thread.h:1105
void notify()
Notify and wake a waiting thread.
Definition: thread.h:349
SmartLock< MutexRW > Lock
Write Lock object type, general Mutex interface (Mutex::Lock will also work) – see SmartLock...
Definition: thread.h:133
bool join()
Join all threads by waiting for them to stop.
Definition: thread.h:1212
bool active() const
Get whether thread is active (running).
Definition: thread.h:947
bool cancel_join(bool locked=false)
Cancels and joins thread.
Definition: thread.h:874
ulong get_tid()
Get current thread ID from system.
Definition: thread.h:41
bool thread_join()
Join thread by waiting for thread to stop.
Definition: thread.h:626
void lock()
Lock associated mutex.
Definition: thread.h:425
Thread::Init ThreadInit
Thread init type
Definition: thread.h:1106
void lock()
Write-Lock mutex.
Definition: thread.h:173
bool join()
Join thread by waiting for thread to stop.
Definition: thread.h:961
Smart locking for synchronization.
Definition: lock.h:28
static void yield()
Definition: systhread.h:129
SmartLock< MutexRW > LockWrite
Write Lock object type – see SmartLock.
Definition: thread.h:134
virtual ~ThreadGroup()
Destructor.
Definition: thread.h:1131
SmartSleepLock< AtomicFlag > SleepLock
Sleep-Lock object type – see SmartSleepLock.
Definition: thread.h:56
bool trylock()
Try to lock associated mutex, fail if already locked (non-blocking).
Definition: thread.h:406
void lock_read()
Read-Lock mutex.
Definition: thread.h:206
Init(Func func, void *arg=NULL)
Definition: thread.h:544
void lock_notify_all()
Lock associated mutex, call notify_all(), then unlock.
Definition: thread.h:456
bool trylock()
Try to Write-Lock mutex without blocking.
Definition: thread.h:153
ThreadClass & thread_cancel(bool locked=false)
Set cancel flag to signal thread to stop, and wake thread via condition object.
Definition: thread.h:730
Inert lock that doesn&#39;t do anything.
Definition: thread_inert.h:27
void * arg
Argument for thread function.
Definition: thread.h:539
static void set_timespec_tv(struct timespec &tm, struct timeval &tv)
Definition: sys.h:1533
SmartSleepLock & lock(ulong sleep_ms=1)
Lock object, if not already locked by this.
Definition: lock.h:169
MutexT mutex_
Definition: thread.h:1242
static void add_timespec_ms(struct timespec &tm, ulong ms)
Definition: sys.h:1546
Initialization structure for starting a function-based thread.
Definition: thread.h:537
static T * instance()
Get singleton instance.
Definition: thread.h:1265
bool trylock(ulong timeout_ms)
Try to lock associated mutex with a timeout.
Definition: thread.h:418
Evo atomic types.
ulong size() const
Get thread group size.
Definition: thread.h:1157
Thread(const Init &init)
Constructor for function-based thread.
Definition: thread.h:567
pthread_cond_t Handle
Definition: thread.h:280
Node * last_
Definition: thread.h:1239
void lock()
Spin-lock flag.
Definition: atomic.h:234
void unlock()
Unlock associated mutex.
Definition: thread.h:431
std::function< void(void *)> Func
Thread function type – with C++11 supports lambda/functor, otherwise just function pointer ...
Definition: thread.h:531
bool active() const
Get whether thread is active (running).
Definition: thread.h:846
Evo C++ Library namespace.
Definition: alg.h:11
Manages a group of threads with shared state.
Definition: thread.h:1104
Thread(Func func, void *arg=NULL)
Constructor for function-based thread.
Definition: thread.h:561
#define EVO_ATOMIC_RELEASE
Release (end) memory ordering barrier started with "consume" or "acquire" barrier.
Definition: atomic.h:30
Spin-lock for thread synchronization.
Definition: thread.h:54
virtual bool thread_detach()
Detach thread to run in background.
Definition: thread.h:613
bool trylock_read()
Try to Read-Lock mutex without blocking.
Definition: thread.h:189
bool lock_wait(ulong timeout_ms=Condition::INF)
Lock associated mutex, call wait(), then unlock.
Definition: thread.h:438
pthread_t Handle
Definition: systhread.h:97
SpinLock()
Constructor.
Definition: thread.h:59
bool owned
Whether associated mutex is owned by this – do not modify.
Definition: thread.h:464
ulong size_
Definition: thread.h:1237
void unlock_read()
Read-Unlock mutex.
Definition: thread.h:217
bool thread_start()
Start thread.
Definition: thread.h:596
Base class for managing a single class-based thread of execution.
Definition: thread.h:706
Manages a singleton instance for given type.
Definition: thread.h:1261
ThreadScope< Thread > This
Definition: thread.h:925
void unlock()
Unlock mutex.
Definition: systhread.h:288
~ThreadScope()
Destructor joins thread.
Definition: thread.h:935
ThreadScope()
Constructor starts thread.
Definition: thread.h:830
Condition()
Default constructor.
Definition: thread.h:287
SmartLockRead< MutexRW > LockRead
Read Lock object type – see SmartLockRead.
Definition: thread.h:135
bool thread_active_
Definition: thread.h:646
Init thread_init
Thread function pointer
Definition: thread.h:551
Smart read-locking for synchronization.
Definition: lock.h:87
SysThread thread_impl_
Definition: thread.h:645
ThreadInit thread_init
Thread init values for function-based threads, not used for class-based threads
Definition: thread.h:1232
bool thread_cancel_join(bool locked=false)
Cancels and joins thread.
Definition: thread.h:747
SysThread::Handle thread_handle() const
Get platform-specific thread handle.
Definition: thread.h:580
Init()
Definition: thread.h:541
#define EVO_ATOMIC_CONSUME
Start "consume" memory ordering barrier, usually followed by a matching "release" barrier...
Definition: atomic.h:24
bool trylock()
Try to lock mutex without blocking.
Definition: systhread.h:223
SharedState shared_state
Shared state used by threads.
Definition: thread.h:1231
bool cancelled() const
Get cancel flag.
Definition: thread.h:1151
Condition(Mutex &mutex)
Constructor.
Definition: thread.h:300
static ulong id()
Get current thread ID from system.
Definition: thread.h:641
Creates a single thread of execution in given scope.
Definition: thread.h:924
This & cancel(bool locked=false)
Set cancel flag to signal thread to stop, and wake thread via condition object.
Definition: thread.h:865
SmartLock< Condition > Lock
Lock object type – see SmartLock.
Definition: thread.h:244
bool start(uint count=1)
Create new threads, add to group and start them.
Definition: thread.h:1168
Mutex()
Constructor.
Definition: thread.h:108
static const ulong INF
Infinite wait timeout value.
Definition: thread.h:282
Definition: systhread.h:54
impl::ThreadGroupNode< S, T > Node
Definition: thread.h:1235
void notify_all()
Notify and wake all waiting threads.
Definition: thread.h:356
bool cancel_flag_
Definition: thread.h:1241
Evo basic types and traits.
ThreadGroup(Thread::Func func)
Constructor for function-based thread.
Definition: thread.h:1121