MLIB
Loading...
Searching...
No Matches
thread.h
Go to the documentation of this file.
1
6#pragma once
7
8#include "event.h"
9#include <functional>
10
11namespace mlib {
12
14class thread : public syncbase
15{
16public:
17
19 enum class state
20 {
21 ready,
22 starting,
23 running,
24 ending,
26 };
27
29 thread (std::function<unsigned int ()> func);
30
31 virtual ~thread ();
32
34 virtual void start ();
35
37 void fork ();
38
40 void join ();
41
43 DWORD wait (DWORD time_limit = INFINITE);
44
46 DWORD wait_alertable (DWORD time_limit = INFINITE);
47
49 DWORD wait_msg (DWORD time_limit = INFINITE, DWORD mask = QS_ALLINPUT);
50
52 void rethrow_exception () const;
53
55 DWORD id () const;
56
58 UINT result () const;
59
61 bool is_running () const;
62
64 state get_state () const;
65
67 int priority () const;
68
70 void priority (int pri);
71
72 using syncbase::name;
73
75 virtual void name (const std::string& nam);
76
77protected:
79 thread (const std::string& name = std::string (), DWORD stack_size = 0,
80 PSECURITY_DESCRIPTOR sd = NULL, bool inherit = false);
81
83 virtual bool init ();
84
86 virtual void term ();
87
89 virtual void run ();
90
91 unsigned int exitcode;
92
93private:
94 void initialize (PSECURITY_DESCRIPTOR sd, BOOL inherit);
95 thread& operator= (const thread& t) = delete;
96 thread (const thread& t) = delete;
97
98 DWORD id_;
99 state volatile stat;
100 auto_event created, started;
101 static unsigned int _stdcall entryProc (thread* ts);
102 DWORD stack;
103 std::function<unsigned int ()> thfunc;
104 std::exception_ptr pex;
105};
106
114{
115public:
116 DWORD id () const;
117 HANDLE handle () const;
118 int priority ();
119 void priority (int pri);
120};
121
122// inlines
123
124inline void thread::fork ()
125{
126 start ();
127}
128
129inline void thread::join ()
130{
131 wait (INFINITE);
132}
133
134inline DWORD thread::id () const
135{
136 return id_;
137};
138
139inline UINT thread::result () const
140{
141 return exitcode;
142}
143
144inline bool thread::is_running () const
145{
146 return stat == state::running;
147}
148
150{
151 return stat;
152}
153
154inline int thread::priority () const
155{
156 return GetThreadPriority (handle ());
157}
158
159inline void thread::priority (int pri)
160{
161 SetThreadPriority (handle (), pri);
162}
163
164inline bool thread::init ()
165{
166 return true;
167}
168
169inline void thread::term ()
170{
171}
172
173inline void thread::rethrow_exception () const
174{
175 if (pex)
176 std::rethrow_exception (pex);
177}
178
179// ----------- current_thread inline functions ------------------------------
180
182inline DWORD current_thread::id () const
183{
184 return GetCurrentThreadId ();
185}
186
187inline HANDLE current_thread::handle () const
188{
189 return GetCurrentThread ();
190}
191
194{
195 return GetThreadPriority (GetCurrentThread ());
196}
197
199inline void current_thread::priority (int pri)
200{
201 SetThreadPriority (GetCurrentThread (), pri);
202}
203
212template <typename T>
213concept ThreadDerived = std::derived_from<T, mlib::thread>;
214
215template <ThreadDerived T>
216inline DWORD wait_all (const T* objs, int count, DWORD msec = INFINITE)
217{
218 assert (count < MAXIMUM_WAIT_OBJECTS);
219 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
220 for (int i = 0; i < count; i++)
221 harr[i] = objs[i].handle ();
222
223 DWORD result = WaitForMultipleObjects (count, harr, true, msec);
224 if (result < WAIT_OBJECT_0 + count)
225 {
226 for (int i = 0; i < count; i++)
227 objs[i].rethrow_exception ();
228 }
229
230 return result;
231}
232
233template <ThreadDerived T>
234inline DWORD wait_all (std::initializer_list<const T*> objs, std::chrono::milliseconds limit)
235{
236 assert (objs.size () < MAXIMUM_WAIT_OBJECTS);
237 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
238 int i = 0;
239 for (auto& th : objs)
240 harr[i++] = th->handle ();
241
242 DWORD msec = (DWORD)limit.count ();
243 DWORD result = WaitForMultipleObjects ((DWORD)objs.size (), harr, true, msec);
244 if (result < WAIT_OBJECT_0 + objs.size ())
245 {
246 for (auto& th : objs)
247 th->rethrow_exception ();
248 }
249
250 return result;
251}
252
253template <ThreadDerived T>
254inline DWORD wait_all (std::initializer_list<const T*> objs, DWORD msec = INFINITE)
255{
256 assert (objs.size () < MAXIMUM_WAIT_OBJECTS);
257 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
258 int i = 0;
259 for (auto& th : objs)
260 harr[i++] = th->handle ();
261
262 DWORD result = WaitForMultipleObjects ((DWORD)objs.size (), harr, true, msec);
263 if (result < WAIT_OBJECT_0 + objs.size ())
264 {
265 for (auto& th : objs)
266 th->rethrow_exception ();
267 }
268
269 return result;
270}
271
272template <ThreadDerived T>
273inline DWORD wait_any (const T* objs, int count, DWORD msec = INFINITE)
274{
275 assert (count < MAXIMUM_WAIT_OBJECTS);
276 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
277 for (int i = 0; i < count; i++)
278 harr[i] = objs[i].handle ();
279
280 DWORD result = WaitForMultipleObjects (count, harr, false, msec);
281 if (result < WAIT_OBJECT_0 + count)
282 {
283 for (int i = 0; i < count; i++)
284 objs[i].rethrow_exception ();
285 }
286 return result;
287}
288
289template <ThreadDerived T>
290inline DWORD wait_any (std::initializer_list<const T*> objs, DWORD msec = INFINITE)
291{
292 assert (objs.size () < MAXIMUM_WAIT_OBJECTS);
293 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
294 int i = 0;
295 for (auto& th : objs)
296 harr[i++] = th->handle ();
297
298 DWORD result = WaitForMultipleObjects ((DWORD)objs.size (), harr, false, msec);
299 if (result < WAIT_OBJECT_0 + objs.size ())
300 {
301 for (auto& th : objs)
302 th->rethrow_exception ();
303 }
304 return result;
305}
306
307template <ThreadDerived T>
308inline DWORD wait_any (std::initializer_list<const T*> objs, std::chrono::milliseconds timeout)
309{
310 assert (objs.size () < MAXIMUM_WAIT_OBJECTS);
311 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
312 int i = 0;
313 for (auto& th : objs)
314 harr[i++] = th->handle ();
315 DWORD msec = (DWORD)timeout.count ();
316 DWORD result = WaitForMultipleObjects ((DWORD)objs.size (), harr, false, msec);
317 if (result < WAIT_OBJECT_0 + objs.size ())
318 {
319 for (auto& th : objs)
320 th->rethrow_exception ();
321 }
322 return result;
323}
324
325template <ThreadDerived T>
326inline DWORD wait_msg (const T* objs, int count, bool all = true, DWORD msec = INFINITE,
327 DWORD mask = QS_ALLINPUT)
328{
329 assert (count < MAXIMUM_WAIT_OBJECTS);
330 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
331 for (int i = 0; i < count; i++)
332 harr[i] = objs[i].handle ();
333
334 DWORD result = MsgWaitForMultipleObjects (count, harr, all, msec, mask);
335 if (result < WAIT_OBJECT_0 + count)
336 {
337 for (int i = 0; i < count; i++)
338 objs[i].rethrow_exception ();
339 }
340 return result;
341}
342
343template <ThreadDerived T>
344inline DWORD wait_msg (std::initializer_list<const T*> objs, bool all = true, DWORD msec = INFINITE,
345 DWORD mask = QS_ALLINPUT)
346{
347 assert (objs.size () < MAXIMUM_WAIT_OBJECTS);
348 HANDLE harr[MAXIMUM_WAIT_OBJECTS];
349 int i = 0;
350 for (auto& th : objs)
351 harr[i++] = th->handle ();
352
353 DWORD result = MsgWaitForMultipleObjects ((DWORD)objs.size (), harr, all, msec, mask);
354 if (result < WAIT_OBJECT_0 + objs.size ())
355 {
356 for (auto& th : objs)
357 th->rethrow_exception ();
358 }
359 return result;
360}
361
363
364} // namespace mlib
Event objects that reset automatically after a successful wait.
Definition event.h:47
Currently executing thread object.
Definition thread.h:114
DWORD id() const
Return ID of current thread.
Definition thread.h:182
int priority()
Return priority current thread.
Definition thread.h:193
Base class for all named synchronization objects.
Definition syncbase.h:27
HANDLE handle() const
Return OS handle of this object.
Definition syncbase.h:54
virtual void wait()
Wait for object to become signaled.
Definition syncbase.h:86
virtual const std::string & name() const
Return object's name.
Definition syncbase.h:60
Wrapper for a Windows thread.
Definition thread.h:15
void fork()
Another name for start () function.
Definition thread.h:124
DWORD wait_msg(DWORD time_limit=INFINITE, DWORD mask=QS_ALLINPUT)
Wait for thread to finish or a message to be queued.
Definition thread.cpp:225
state get_state() const
Return thread's execution status.
Definition thread.h:149
virtual bool init()
Initialization function called before run.
Definition thread.h:164
void rethrow_exception() const
Rethrow an exception usually in the context of another thread.
Definition thread.h:173
bool is_running() const
Return true if thread is running.
Definition thread.h:144
DWORD wait_alertable(DWORD time_limit=INFINITE)
Wait for thread to finish or an APC, or IO completion routine to occur.
Definition thread.cpp:207
virtual void run()
Default run function.
Definition thread.cpp:154
int priority() const
Return thread's priority.
Definition thread.h:154
state
Execution state of a thread.
Definition thread.h:20
@ starting
in the process of starting up
@ running
is running
@ finished
execution finished
@ ready
not started
@ ending
in the process of finishing
UINT result() const
Return thread's exit code.
Definition thread.h:139
virtual ~thread()
Destructor.
Definition thread.cpp:105
void join()
Another name for wait () function.
Definition thread.h:129
DWORD id() const
Return thread's ID.
Definition thread.h:134
virtual void term()
Finalization function called after run.
Definition thread.h:169
virtual void start()
Begin execution of a newly created thread.
Definition thread.cpp:168
unsigned int exitcode
exit code
Definition thread.h:91
virtual const std::string & name() const
Return object's name.
Definition syncbase.h:60
Specialization of wait functions for threads, re-throw any exceptions that might have occurred during...
Definition thread.h:213
event class definition.
DWORD wait_any(const T *objs, int count, DWORD msec=INFINITE)
Wait for multiple objects until any of them becomes signaled.
Definition syncbase.h:244
DWORD wait_all(const T *objs, int count, DWORD msec=INFINITE)
Wait for multiple objects until all become signaled.
Definition syncbase.h:171
DWORD wait_msg(const T *objs, int count, bool all=true, DWORD msec=INFINITE, DWORD mask=QS_ALLINPUT)
Wait for multiple objects or a message to be queued.
Definition syncbase.h:318