Honeycomb  0.1
Component-Model Framework
Thread.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
4 #include "Honey/Misc/Exception.h"
5 #include "Honey/Chrono/Clock.h"
6 #include "Honey/Thread/platform/Thread.h"
7 
8 namespace honey
9 {
10 
11 class Thread;
12 class Condition;
13 class Mutex;
14 
16 namespace thread
17 {
19  namespace priv
20  {
21  struct StoreId
22  {
23  StoreId(int id = -1) : id(id), reclaim(0) {}
24  int id;
25  int reclaim;
26  };
27 
28  struct Store
29  {
30  Store() : ptr(nullptr), reclaim(-1), fin(bind(finalize<void>(), ptr)) {}
31  void* ptr;
32  int reclaim;
33  function<void ()> fin;
34  };
35 
37  class InterruptWait : mt::NoCopy
38  {
39  public:
40  InterruptWait(Thread& thread, Condition& cond, Mutex& mutex);
41  ~InterruptWait();
42  private:
43  Thread& thread;
44  };
45  }
48  namespace current
50  {
52  inline void yield() { platform::yield(); }
54  inline void pause() { platform::pause(); }
56  void sleep(MonoClock::Duration time);
58  void sleep(MonoClock::TimePoint time);
60  inline void spin(int count) { for (int i = 0; i < count; ++i) pause(); }
62  bool interruptEnabled();
64  void interruptPoint();
65  }
66 
68  template<class T>
69  class Local
70  {
71  public:
72  typedef function<T* ()> Init;
73  typedef function<void (T*)> Fin;
74 
76  Local(const Init& init = []{ return new T(); }, const Fin& fin = finalize<T>());
77  ~Local();
78 
80  Local& operator=(const T& rhs) { get() = rhs; return *this; }
81 
82  operator const T&() const { return get(); }
83  operator T&() { return get(); }
84  const T* operator->() const { return &get(); }
85  T* operator->() { return &get(); }
86  const T& operator*() const { return get(); }
87  T& operator*() { return get(); }
88 
89  const T& get() const { const_cast<Local*>(this)->get(); }
90 
92  T& get();
93 
94  private:
95  priv::StoreId _id;
96  Init _init;
97  Fin _fin;
98  };
99 
102 
104 
114  {
115  InterruptEnable(bool enable);
117  private:
118  Thread& thread;
119  bool saveState;
120  };
121 }
122 
123 
124 class ConditionLock;
125 class SpinLock;
126 
128 class Thread : platform::Thread, mt::NoCopy
129 {
130  typedef platform::Thread Super;
131  friend class platform::Thread;
133  friend bool thread::current::interruptEnabled();
134  friend void thread::current::interruptPoint();
135  template<class T> friend class thread::Local;
136  friend struct thread::InterruptEnable;
138 
139 public:
140  typedef Super::ThreadId ThreadId;
141  typedef function<void ()> Entry;
142 
144 
148  Thread(const Entry& entry, int stackSize = 0);
150  Thread(Thread&& rhs) noexcept;
151  virtual ~Thread();
152 
153  Thread& operator=(Thread&& rhs);
154 
156  static Thread& current() { return static_cast<Thread&>(Super::current()); }
157 
159  void start();
160 
162  void join() { join(MonoClock::TimePoint::max()); }
164  bool join(MonoClock::Duration time) { return join(time == time.max() ? MonoClock::TimePoint::max() : MonoClock::now() + time); }
166  bool join(MonoClock::TimePoint time);
167 
169 
172  void interrupt(const Exception::ConstPtr& e = new thread::Interrupted);
174  bool interruptRequested() const;
175 
179  static int priorityNormal() { return Super::priorityNormal(); }
180  static int priorityMin() { return Super::priorityMin(); }
181  static int priorityMax() { return Super::priorityMax(); }
183 
185  void setPriority(int priority) { Super::setPriority(priority); }
187  int getPriority() const { return Super::getPriority(); }
188 
190  static const ThreadId threadIdInvalid;
192  ThreadId threadId() const { return Super::threadId(); }
193 
195  static int concurrency() { return Super::concurrency(); }
196 
197 private:
198  typedef thread::priv::StoreId StoreId;
199  typedef thread::priv::Store Store;
200 
202  Thread(bool external, int stackSize);
203  void finalize();
204 
206  void entry();
207 
209  static StoreId allocStore();
211  static void freeStore(StoreId id);
213  Store& store(const StoreId& id) { const_cast<Thread*>(this)->expandStore(id.id); return _stores[id.id]; }
215  void expandStore(int id) { if (id < (int)_stores.size()) return; _stores.resize(id*2+1); }
216 
217  Entry _entry;
218  UniquePtr<SpinLock> _lock;
219  bool _started;
220  bool _done;
221  UniquePtr<ConditionLock> _doneCond;
222  UniquePtr<ConditionLock> _sleepCond;
223 
224  bool _interruptEnable;
225  Exception::ConstPtr _interruptEx;
226  Condition* _interruptCond;
227  Mutex* _interruptMutex;
228 
229  vector<Store> _stores;
230 
231  struct Static
232  {
233  Static();
234  ~Static();
235 
236  vector<StoreId> storeIds;
237  int storeCount;
238  UniquePtr<SpinLock> storeLock;
239  };
240  static mt_global(Static, getStatic,);
241 };
242 
243 
244 namespace thread
245 {
246  template<class T>
247  Local<T>::Local(const Init& init, const Fin& fin) : _id(Thread::allocStore()), _init(init), _fin(fin) {}
248 
249  template<class T>
250  Local<T>::~Local() { Thread::freeStore(_id); }
251 
252  template<class T>
254  {
255  priv::Store& store = Thread::current().store(_id);
256  //This thread may not have init the ptr yet, or the ptr could be from an old local that has been deleted
257  if (store.reclaim != _id.reclaim)
258  {
259  store.fin();
260  store.reclaim = _id.reclaim;
261  T* ptr = _init();
262  store.ptr = ptr;
263  //store.fin = std::bind(_fin, ptr); //TODO: clang bug, uncomment to properly destroy thread locals
264  store.fin = std::bind(finalize<T>(), ptr);
265  }
266  return *reinterpret_cast<T*>(store.ptr);
267  }
268 }
269 
270 }
T & operator*()
Definition: Thread.h:87
static int priorityMin()
Definition: Thread.h:180
void yield()
Give up this thread's time slice to allow other threads to execute.
Definition: Thread.h:52
bool interruptEnabled()
Check whether interrupts are enabled for this thread.
Definition: Thread.cpp:44
const T & operator*() const
Definition: Thread.h:86
friend class platform::Thread
Definition: Thread.h:131
static TimePoint now()
Get current time.
Definition: Clock.h:48
Thread class.
Definition: Thread.h:128
static int priorityNormal()
Definition: Thread.h:179
A thread lock where the lock is acquired through a busy wait loop.
Definition: Spin.h:17
InterruptEnable(bool enable)
Definition: Thread.cpp:58
Inherit to declare that class is not copyable.
Definition: Meta.h:286
void setPriority(int priority)
Set thread execution scheduling priority.
Definition: Thread.h:185
~InterruptEnable()
Definition: Thread.cpp:63
static int concurrency()
Get number of threads that can be executed concurrently on the device.
Definition: Thread.h:195
Super::TimePoint TimePoint
Definition: Clock.h:40
void spin(int count)
Suspend this thread momentarily without giving up its time slice. The thread will pause count times...
Definition: Thread.h:60
Thread(const Entry &entry, int stackSize=0)
Construct a thread.
Definition: Thread.cpp:89
function< void(T *)> Fin
Definition: Thread.h:73
const T & get() const
Definition: Thread.h:89
Lock that is bound to a single condition. This is the common usage case of condition variables...
Definition: Lock.h:33
void pause()
Perform a no-op without giving up this thread's time slice. This no-op momentarily frees resources fo...
Definition: Thread.h:54
static int priorityMax()
Definition: Thread.h:181
#define EXCEPTION(Class)
Declares methods required for every subclass of honey::Exception.
Definition: Exception.h:17
void sleep(MonoClock::Duration time)
Suspend this thread for an amount of time.
Definition: Thread.cpp:35
Super::ThreadId ThreadId
Definition: Thread.h:140
const T * operator->() const
Definition: Thread.h:84
Local & operator=(const T &rhs)
Assign thread-local object to rhs.
Definition: Thread.h:80
static Thread & current()
Get the thread object of the calling thread.
Definition: Thread.h:156
function< T *()> Init
Definition: Thread.h:72
~Local()
Definition: Thread.h:250
Local thread storage. Multiple threads can access one Local object, but each thread will only see its...
Definition: Thread.h:69
Interrupted exception.
Definition: Thread.h:101
Base exception class. Exceptions inherited from this class provide debug info and can be thrown polym...
Definition: Exception.h:45
Enable / disable interrupts in the current thread's scope.
Definition: Thread.h:113
Functor to delete a pointer.
Definition: Allocator.h:161
T * operator->()
Definition: Thread.h:85
static const ThreadId threadIdInvalid
Invalid thread id.
Definition: Thread.h:190
void interrupt(const Exception::ConstPtr &e=new thread::Interrupted)
Request an interrupt in the thread.
Definition: Thread.cpp:156
friend class thread::priv::InterruptWait
Definition: Thread.h:137
ThreadId threadId() const
Get the thread unique platform id.
Definition: Thread.h:192
int getPriority() const
Get thread execution scheduling priority.
Definition: Thread.h:187
TimePoint::Duration Duration
Definition: Clock.h:41
Local(const Init &init=[]{return new T();}, const Fin &fin=finalize< T >())
Init / Finalize func is called once per thread to create/destroy local object instance.
Definition: Thread.h:247
bool interruptRequested() const
Check whether an interrupt has been requested for the thread.
Definition: Thread.cpp:167
bool join(MonoClock::Duration time)
Try to join for an amount of time. Returns true if joined and thread execution is complete...
Definition: Thread.h:164
Global Honeycomb namespace.
void join()
Wait until thread execution is complete.
Definition: Thread.h:162
void interruptPoint()
Throw an exception if interrupt is enabled and has been requested in this thread. ...
Definition: Thread.cpp:46
function< void()> Entry
Definition: Thread.h:141
void start()
Begin execution of this thread. The entry function will be called.
Definition: Thread.cpp:128