uvw  1.3.0
thread.hpp
1 #pragma once
2 
3 
4 #include <memory>
5 #include <string>
6 #include <type_traits>
7 #include <utility>
8 #include <uv.h>
9 #include "loop.hpp"
10 #include "underlying_type.hpp"
11 
12 
13 namespace uvw {
14 
15 
16 class Thread;
17 class ThreadLocalStorage;
18 class Once;
19 class Mutex;
20 class RWLock;
21 class Semaphore;
22 class Condition;
23 class Barrier;
24 
25 
26 class Thread final: public UnderlyingType<Thread, uv_thread_t> {
27  using InternalTask = std::function<void(std::shared_ptr<void>)>;
28 
29  static void createCallback(void *arg) {
30  Thread &thread = *(static_cast<Thread*>(arg));
31  thread.task(thread.data);
32  }
33 
34 public:
35  using Task = InternalTask;
36  using Type = uv_thread_t;
37 
38  explicit Thread(ConstructorAccess ca, std::shared_ptr<Loop> ref, InternalTask t, std::shared_ptr<void> d = nullptr) noexcept
39  : UnderlyingType{ca, std::move(ref)}, data{std::move(d)}, task{std::move(t)}
40  {}
41 
42  static Type self() noexcept {
43  return uv_thread_self();
44  }
45 
46  static bool equal(const Thread &tl, const Thread &tr) noexcept {
47  return !(0 == uv_thread_equal(tl.get(), tr.get()));
48  }
49 
50  ~Thread() noexcept {
51  join();
52  }
53 
54  bool run() noexcept {
55  return (0 == uv_thread_create(get(), &createCallback, this));
56  }
57 
58  bool join() noexcept {
59  return (0 == uv_thread_join(get()));
60  }
61 
62 private:
63  std::shared_ptr<void> data;
64  Task task;
65 };
66 
67 
68 class ThreadLocalStorage final: public UnderlyingType<ThreadLocalStorage, uv_key_t> {
69 public:
70  explicit ThreadLocalStorage(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept
71  : UnderlyingType{ca, std::move(ref)}
72  {
73  uv_key_create(UnderlyingType::get());
74  }
75 
76  ~ThreadLocalStorage() noexcept {
77  uv_key_delete(UnderlyingType::get());
78  }
79 
80  template<typename T>
81  T* get() noexcept {
82  return static_cast<T*>(uv_key_get(UnderlyingType::get()));
83  }
84 
85  template<typename T>
86  void set(T *value) noexcept {
87  return uv_key_set(UnderlyingType::get(), value);
88  }
89 };
90 
91 
92 // `Once` is an odd one as it doesn't use a `libuv` structure per object.
93 class Once final: public UnderlyingType<Once, uv_once_t> {
94  static uv_once_t* guard() noexcept {
95  static uv_once_t once = UV_ONCE_INIT;
96  return &once;
97  }
98 
99 public:
100  using UnderlyingType::UnderlyingType;
101 
102  template<typename F>
103  static void once(F &&f) noexcept {
104  using CallbackType = void (*)(void);
105  static_assert(std::is_convertible<F, CallbackType>::value, "!");
106  CallbackType cb = f;
107  uv_once(guard(), cb);
108  }
109 };
110 
111 
112 class Mutex final: public UnderlyingType<Mutex, uv_mutex_t> {
113  friend class Condition;
114 
115 public:
116  explicit Mutex(ConstructorAccess ca, std::shared_ptr<Loop> ref, bool recursive = false) noexcept
117  : UnderlyingType{ca, std::move(ref)}
118  {
119  if(recursive) {
120  uv_mutex_init_recursive(get());
121  } else {
122  uv_mutex_init(get());
123  }
124  }
125 
126  ~Mutex() noexcept {
127  uv_mutex_destroy(get());
128  }
129 
130  void lock() noexcept {
131  uv_mutex_lock(get());
132  }
133 
134  bool tryLock() noexcept {
135  return (0 == uv_mutex_trylock(get()));
136  }
137 
138  void unlock() noexcept {
139  uv_mutex_unlock(get());
140  }
141 };
142 
143 
144 class RWLock final: public UnderlyingType<RWLock, uv_rwlock_t> {
145 public:
146  explicit RWLock(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept
147  : UnderlyingType{ca, std::move(ref)}
148  {
149  uv_rwlock_init(get());
150  }
151 
152  ~RWLock() noexcept {
153  uv_rwlock_destroy(get());
154  }
155 
156  void rdLock() noexcept {
157  uv_rwlock_rdlock(get());
158  }
159 
160  bool tryRdLock() noexcept {
161  return (0 == uv_rwlock_tryrdlock(get()));
162  }
163 
164  void rdUnlock() noexcept {
165  uv_rwlock_rdunlock(get());
166  }
167 
168  void wrLock() noexcept {
169  uv_rwlock_wrlock(get());
170  }
171 
172  bool tryWrLock() noexcept {
173  return (0 == uv_rwlock_trywrlock(get()));
174  }
175 
176  void wrUnlock() noexcept {
177  uv_rwlock_wrunlock(get());
178  }
179 };
180 
181 
182 class Semaphore final: public UnderlyingType<Semaphore, uv_sem_t> {
183 public:
184  explicit Semaphore(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int value) noexcept
185  : UnderlyingType{ca, std::move(ref)}
186  {
187  uv_sem_init(get(), value);
188  }
189 
190  ~Semaphore() noexcept {
191  uv_sem_destroy(get());
192  }
193 
194  void post() noexcept {
195  uv_sem_post(get());
196  }
197 
198  void wait() noexcept {
199  uv_sem_wait(get());
200  }
201 
202  bool tryWait() noexcept {
203  return (0 == uv_sem_trywait(get()));
204  }
205 };
206 
207 
208 class Condition final: public UnderlyingType<Condition, uv_cond_t> {
209 public:
210  explicit Condition(ConstructorAccess ca, std::shared_ptr<Loop> ref) noexcept
211  : UnderlyingType{ca, std::move(ref)}
212  {
213  uv_cond_init(get());
214  }
215 
216  ~Condition() noexcept {
217  uv_cond_destroy(get());
218  }
219 
220  void signal() noexcept {
221  uv_cond_signal(get());
222  }
223 
224  void broadcast() noexcept {
225  uv_cond_broadcast(get());
226  }
227 
228  void wait(Mutex &mutex) noexcept {
229  uv_cond_wait(get(), mutex.get());
230  }
231 
232  bool timedWait(Mutex &mutex, uint64_t timeout) noexcept {
233  return (0 == uv_cond_timedwait(get(), mutex.get(), timeout));
234  }
235 };
236 
237 
238 class Barrier final: public UnderlyingType<Barrier, uv_barrier_t> {
239 public:
240  explicit Barrier(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int count) noexcept
241  : UnderlyingType{ca, std::move(ref)}
242  {
243  uv_barrier_init(get(), count);
244  }
245 
246  ~Barrier() noexcept {
247  uv_barrier_destroy(get());
248  }
249 
250  bool wait() noexcept {
251  return (0 == uv_barrier_wait(get()));
252  }
253 };
254 
255 
256 }
uvw default namespace.
Definition: async.hpp:11