Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
Thread.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Execution_Thread_h_
5#define _Stroika_Foundation_Execution_Thread_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <functional>
10#include <map>
11#include <optional>
12#include <thread>
13
14#include "Stroika/Foundation/Common/Common.h"
16#include "Stroika/Foundation/Execution/Exceptions.h"
17#include "Stroika/Foundation/Execution/Signals.h"
20
21/**
22 * \file
23 *
24 * TODO
25 * @todo Probably no longer need siginterrupt () calls, since we DON'T set SA_RESTART in our call to sigaction().
26 */
28 class String;
29}
30
32
33 /**
34 * This is only meant for debugging. If true, track the running threads (and provide API to access)
35 * and DbgTrace() automatically in construction/destruction.
36 */
37#ifndef qStroika_Foundation_Execution_Thread_SupportThreadStatistics
38#define qStroika_Foundation_Execution_Thread_SupportThreadStatistics qStroika_Foundation_Debug_AssertionsChecked
39#endif
40
41 /**
42 * \brief Thread is a namespace for Stroika thread code, @see Thread::Ptr or @Thread::New
43 *
44 * Stroika Threads are built on std::jthread, so can be used mostly interoperably. However,
45 * Stroika threads add a number of very useful features to std::threads:
46 * o Simpler Cancelation/Interruption/Aborting
47 * (c++ 20 introduces thread cancelation via explicitly managed stop_tokens, but Stroika's thread cancelation
48 * uses this, but hides it - mostly).
49 * o EINTR handling (POSIX only)
50 *
51 * \note ***Which standard libraries actually have jthread/stop_token***
52 *
53 * Much of the Stroika thread code checks defined(__cpp_lib_jthread);
54 * Where it fails, Thread holds a std::thread rather than a
55 * std::jthread, has no stop_source, and Abort () does not call request_stop () - leaving only
56 * the interrupt signal (POSIX) or APC (Windows) to break into a blocking call.
57 *
58 * o libstdc++ - has jthread/stop_token, since GCC 10, so every gcc Stroika supports is fine
59 * o MS Visual Studio - has jthread/stop_token
60 * o libc++ - implemented jthread/stop_token in LLVM 18, but guarded behind -fexperimental-library until
61 * LLVM 20, and Stroika passes that flag nowhere. So EVERY --stdlib libc++ build with
62 * clang < 20 lacks it - today that is the clang++-15/16/17/18-*-libc++ regression
63 * configurations. @see https://libcxx.llvm.org/Status/Cxx20.html
64 * o Apple XCode - 15 and 16 lack it, 26.3 has it (measured 2026-09-10 with each SDK
65 * pinned via -isysroot; note DEVELOPER_DIR alone does NOT steer the headers, so a
66 * probe without it silently measures the CommandLineTools libc++ instead). Apple
67 * renumbered Xcode 16 -> 26, so there is no Xcode 17-25; Xcode 26.3 reports itself
68 * as Apple clang 17.0.0, which is a compiler version, not an Xcode one.
69 *
70 * Anywhere this matters, prefer a mechanism that does not depend on it - @see
71 * qStroika_Foundation_Execution_WaitForIOReady_UsePPoll for a worked example.
72 * -- checked against libc++ upstream status 2026-09-09
73 *
74 * as well as a couple modestly helpful features (that can be done other ways directly with std::thread):
75 * o Copyability (using Thread::Ptr)
76 * o Better lifetime management (the thread envelope - object you create - can go away, but
77 * the underlying thread can continue running, with its memory/resources being cleaned
78 * up autoamtically.
79 * o And several minor features like (mostly) portably setting thread priorities, names, etc and more
80 *
81 * Note - the cancelation feature is very handy for building large scale applications which use
82 * worker tasks and things like thread pools, to be able to reclaim resources, cancel ongoing operations
83 * as useless, and maintain overall running system integrity.
84 *
85 * Using the smartpointer wrapper Thread around a thread guarantees its reference counting
86 * will work safely - so that even when all external references go away, the fact that the thread
87 * is still running will keep the reference count non-zero.
88 *
89 * Thread Aborting:
90 * The Stroika Thread class supports the idea of 'aborting' a thread (cooperatitve cancelation)
91 *
92 * Thread Interruoption:
93 * Stroika v2.1 and earlier supported a feature like Thread-Abort, called 'Interrupt' - that acted like
94 * thread abort, except that it was not sticky - and once the interrupt was handled, it 'reset' to not
95 * interrupting anymore.
96 *
97 * I never really found any compelling use case for this idea (borrowed from java thread interrupt).
98 *
99 * And I think the scenarios where it MIGHT be helpful, could be handled just as easily with
100 * condition variables.
101 *
102 * Also, c++20 added support which allows thead aborting (stop_token), but that doesn't work well/easily
103 * for basic interruption.
104 *
105 * So - abandoned Thread::Interrupt(...) in Stroika v3.
106 *
107 * \em Nomenclature Note:
108 * In some libraries, the term interruption, cancelation is used for thread aborting.
109 * > java uses interruption
110 * > boost uses cancelation,
111 * > POSIX uses cancelation (pthread_canel)
112 * > and .net uses Interrupt and Abort
113 *
114 * The basic idea is that a thread goes off on its own, doing stuff, and an external force
115 * decides to tell it to stop.
116 *
117 * Examples of this might be:
118 * (1) A search user interface, which starts searching as the user types. Once the process
119 * has received a certain number of characters it starts searching, but perhaps before
120 * the search is done, another character comes in, so the GUI code will want to Abort
121 * the existing search, and start a new one (with the extra character(s)).
122 * (2) A web server - which is serving up content, and it told to shut-down. It must interrupt
123 * existing in process processes - some maybe handling a read/write sequence, and some
124 * perhaps doing a socket listen/accept call.
125 *
126 * When a thread is aborted, it (in that thread) throws
127 * class AbortException;
128 *
129 * Thread 'interruption' happens via 'cancelation points'. Cancelation points are points in the code
130 * where we check to see if the current running thread has been interrupted (or aborted) and raise
131 * the appropriate exception.
132 *
133 * This mechanism is almost completely co-operative, meaning that user
134 * code must call CheckForInterruption () in the right places to make interruption work. But Stroika
135 * is structured to make that happen automatically throughout most of its code, but having key routines (like Sleep, and WaitableEvents)
136 * automatically internally be cancelation points.
137 *
138 * The only slight exception to this is on Windows, where we have the APC mechanism that will interupt a wide vareity of windows
139 * system calls (see docs below).
140 *
141 * \note - its important that this 'interruption' can only happen at well defined times, because that allows
142 * for safe and reliable cleanup of whatever activitites were being done (e.g. cannot interupt in a destructor)
143 *
144 * Thread interruption/aborting is tricky todo safely and portably. We take a safe, cooperative approach.
145 * (1) We maintain a thread-local-storage variable - saying if this thread has been aborted.
146 * Sprinkling CheckForInterruption throughout your code - will trigger an InterupptedException () or AbortException ()
147 * in that thread context. Note a pointer to that TLS interruption variable is also stored
148 * in the thread 'rep' object, so it can be set (by Thread::Interrupt).
149 *
150 * (2) WINDOWS ONLY: Async-injection (QueueUserAPC/Windows) - Alertable state - certain (alertable) functions get interrupted and return
151 * WAIT_IO_COMPLETION (like POSIX EINTR).
152 *
153 * @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa363772(v=vs.85).aspx
154 * o SleepEx
155 * o WaitForSingleObjectEx
156 * o WaitForMultipleObjectsEx
157 * o SignalObjectAndWait
158 * o MsgWaitForMultipleObjectsEx
159 * But also from https://msdn.microsoft.com/en-us/library/windows/desktop/ms741669(v=vs.85).aspx
160 * o WSAPoll ... Winsock performs an alertable, similarly for recvfrom, accept, etc. Not clear how to get full list of
161 * windows alertable functions...
162 *
163 * This allows interrupting windows waiting / blocking functions (most of them).
164 *
165 * (3) POSIX ONLY: Signal injection - we send a special (defaults to SIG_USR2) signal to a particular thread.
166 * This triggers an EINTR on most UNIX system calls, which are automatically restarted in most cases
167 * (@see Execution::Handle_ErrNoResultInterruption), but in case of interruption, we call
168 * CheckForInterruption ()
169 *
170 * This allows interrupting UNIX waiting / blocking functions (all of them?).
171 *
172 * \note @see defails on cancelation points, because many common std C++ blocking operations, like std::mutex are not
173 * std::condition_variable are not cancelation points and so can break this mechanism if not used carefully
174 *
175 * Handle_ErrNoResultInterruption()
176 * The short of it is that you need to catch EINTR and restart the call for these system calls:
177 * o read, readv, write, writev, ioctl
178 * o open() when dealing with a fifo
179 * o wait*
180 * o Anything socket based (send*, recv*, connect, accept etc)
181 * o flock and lock control with fcntl
182 * o mq_ functions which can block
183 * o futex
184 * o sem_wait (and timed wait)
185 * o pause, sigsuspend, sigtimedwait, sigwaitinfo
186 * o poll, epoll_wait, select and 'p' versions of the same
187 * o msgrcv, msgsnd, semop, semtimedop
188 * o close (although, on Linux, EINTR won't happen here)
189 * o any sleep functions (careful, you need to handle this are restart with
190 * different arguments)
191 * This is integrated with Stroika's thread cancelation mechanism.
192 *
193 * @see Handle_ErrNoResultInterruption
194 *
195 * ***Thread Cancelation Points***
196 * A cancelation point is any (typically but not always blocking) function which will be interrupted (cause interruption exception) and stop blocking,
197 * when someone calls Thread::Interupt or Thread::Abort() on its thread object.
198 *
199 * Roughly, these are subroutines which call
200 * CheckForInterruption ()
201 * frequently, internally.
202 *
203 * As its crucial to understand this in the API, we document each such function with ***Cancelation Point*** in its doc header.
204 * For example, the Sleep() overloads are cancelation points.
205 *
206 * Equally important to understand, is when a function guarantees its NOT a cancelation point - which we will document
207 * with ***Not Cancelation Point***, and typically also noexcept. The DbgTrace () calls fall into this category.
208 *
209 * \note An API marked *** Cancelation Point *** will always CheckForInterruption () at least once (or equivalent check)
210 * and will never block indefinitely without periodically checking for interruption.
211 *
212 * \note Stroika threads lifetime must NOT extend outside the lifetime of 'main'. That means they cannot
213 * be started by static constructors, and must not be left running past the end of main, to
214 * be shut down by static destructors. The reason for this is that its too hard to guarantee
215 * all the rest of the Stroika infrastructure (signals etc) work properly in that context,
216 * and its do overwhemlingly likely a softare bug waiting to happen.
217 *
218 * If you must have a thread running like that, use std::thread (though I'm not sure how well that
219 * will work either).
220 *
221 * Note the Thread 'smartpointer' wrapper can be constructed/destructed statically (before/after main). You
222 * just cannot start a thread before main, nor allow it to still be running (not completed) before exiting.
223 * #if qStroika_Foundation_Execution_Thread_SupportThreadStatistics (defaults true in debug builds) an attempt
224 * is made to auto-detect this and diagnose it in the tracelog and with assertions.
225 *
226 * \note Considered adding an API to return the underlying std::thread or std::thread::native_handle (), but
227 * have not needed this so far, and it might create some confusion about ownership? Detaching would be
228 * a problem because the owned thread object has hooks into the Stroika Thread object, so that kind of
229 * needs to be left around. I suppose we might want to allow an accessor to std::thread* which is like an
230 * internal pointer (thread safety questions too with that). MAYBE better to just allow construction of a
231 * Stroika Thread from an std::thread (but then we don't have the wrapper logic for maining reference counts).
232 * No compelling need so far, and no obviously best approach.
233 */
234 namespace Thread {
235
236 /**
237 * Thread::IDType is a portable representation which is a key to currently existing system threads.
238 */
239 using IDType = thread::id;
240
241 /**
242 * Thread::native_handle is the type of the underlying handle to a native thread
243 * which can allow for using platform APIs.
244 */
245 using NativeHandleType = thread::native_handle_type;
246
247 /**
248 * \brief EXPERIMENTAL SUPPORT FOR THREAD STACK (and maybe other) settings
249 *
250 * @todo COULD add things like CPU afinity, or thread prority.
251 *
252 * These configuration describe how Stroika will construct new Stroika Thread objects.
253 */
255 /**
256 * \note see https://github.com/SophistSolutions/Stroika/issues/608 (STK-474) - @todo and NYI
257 */
258 optional<size_t> fStackSize;
259
260 /**
261 * \note see https://github.com/SophistSolutions/Stroika/issues/608 (STK-474) - @todo and NYI
262 *
263 * \note NYI - see &&&& - probably availble for POSIX, but not sure for windoze threads
264 * http://man7.org/linux/man-pages/man3/pthread_attr_setguardsize.3.html
265 * Perhaps for windows just add to end of stacksize
266 */
267 optional<size_t> fStackGuard;
268
269#if qStroika_Platform_Windows
270 optional<bool> fThrowInterruptExceptionInsideUserAPC;
271#endif
272 };
273
274 /**
275 * Return or Set the global default configuration for Thread object construction.
276 */
278 Configuration DefaultConfiguration (const optional<Configuration>& newConfiguration);
279
280 /**
281 * optional flag for constructing new threads
282 */
284 eAutoStart
285 };
286
287 /**
288 * Common::DefaultNames<> is defined for this enumeration.
289 */
290 enum class Status : uint8_t {
291 eNotYetRunning, // created, but start not yet called
292 eRunning, // in the context of the 'Run' method
293 eAborting, // Abort () called, but the thread still hasn't yet unwound
294 eCompleted, // run has terminated (possibly by exception, possibly normally, possibly because of Abort call)
295
296 Stroika_Define_Enum_Bounds (eNotYetRunning, eCompleted)
297 };
298
299 /**
300 *
301 * \note Common::DefaultNames<> supported
302 */
303 enum class Priority {
304 eLowest,
305 eBelowNormal,
306 eNormal,
307 eAboveNormal,
308 eHighest,
309
310 Stroika_Define_Enum_Bounds (eLowest, eHighest)
311 };
312
313 /**
314 *
315 */
316 struct ConfigurationStatus : Configuration {
317 /**
318 * Stack starts at base, and grows towards limit - could be up or down.
319 */
320 optional<const byte*> fStackBase;
321
322 /**
323 * @see fStackBase
324 */
325 optional<const byte*> fStackLimit;
326
327 /**
328 * @see fStackBase, fStackLimit
329 */
330 optional<const byte*> fCurrentStackAt;
331
332 /**
333 * Return current stack used, if available
334 *
335 * \note NYI
336 */
337 optional<size_t> GetStackUsed () const;
338
339 /**
340 * Return current stack available, if available
341 *
342 * \note NYI
343 */
344 optional<size_t> GetStackAvailable () const;
345 };
346
347 /**
348 * \brief Thread::Ptr is a (unsynchronized) smart pointer referencing an internally synchronized std::thread object (rep), with special feautres, including cancelation
349 *
350 * \note Since this is a smart pointer, the constness of the methods depends on whether they modify the smart pointer itself, not
351 * the underlying thread object.
352 *
353 * \see Thread::CleanupPtr
354 *
355 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety-For-Envelope-Letter-Internally-Synchronized">C++-Standard-Thread-Safety-For-Envelope-Letter-Internally-Synchronized</a>
356 */
357 class Ptr {
358 private:
359 class Rep_;
360
361 public:
362 /**
363 * \par Example Usage
364 * \code
365 * Thread::Ptr t = Thread::New ([r]() { r->Run (); }, Thread::eAutoStart, "Thread Name");
366 * Thread::Ptr t2 = t;
367 * \endcode
368 */
369 Ptr () = default;
370 Ptr (nullptr_t);
371 Ptr (const Ptr& src);
372 Ptr (Ptr&& src) noexcept;
373
374 protected:
375 Ptr (const shared_ptr<Rep_>& rep);
376
377 public:
378 /**
379 */
380 nonvirtual Ptr& operator= (const Ptr& rhs);
381 nonvirtual Ptr& operator= (Ptr&& rhs) noexcept;
382
383 public:
384 /**
385 * \brief Clear the pointer this Thread smart pointer refers to. This does nothing to affect the state of the underlying thread.
386 *
387 * \Ensure *this == nullptr
388 */
389 nonvirtual void reset () noexcept;
390
391 public:
392 /**
393 * Each thread has associated an std::function, which gets run by the thread. It can be accessed
394 * via GetFunction(), but is only settable in the thread constructor.
395 */
396 nonvirtual function<void ()> GetFunction () const;
397
398 public:
399 /**
400 * \note GetID () may return a default-constructed IDType if the thread is not running (has not been started, or has terminated)
401 */
402 nonvirtual IDType GetID () const;
403
404 public:
405 /**
406 * \note GetNativeHandle () may return a default-constructed NativeHandleType if the thread is not running (has not been started, or has terminated)
407 */
408 nonvirtual NativeHandleType GetNativeHandle () const noexcept;
409
410#if defined(__cpp_lib_jthread)
411 public:
412 /**
413 */
414 nonvirtual stop_token GetStopToken () const;
415#endif
416
417 public:
418 /**
419 * For start method
420 */
422 eWaitUntilStarted
423 };
424
425 public:
426 /**
427 * \pre GetStatus () == Status::eNotYetRunning or Status::eAborting
428 * \pre never called before on this thread object
429 *
430 * Typically you won't call this directly, but instead pass the eStart parameter to the Thread constructor.
431 * But you can explicitly call if you prefer.
432 *
433 * A thread can only be started once. When it is constructed (without eStart) - it starts in the NotYetRunning state. And can
434 * only be started when its in that state.
435 *
436 * The zero argument Start overload returns, with the thread in any possible state.
437 * This function returns quickly, and the state of the thread may not have changed by the time it ru
438 * ensures when it returns the state is running, or completed, but cannot (yet) be aborted?? or null or not yet running
439 *
440 * The Start (WaitUntilStarted) overload waits for the thread to have started (or throws if it cannot start thread). Note the thread
441 * can still run to completion, or be aborted somewhere along the lines. So in this case:
442 * Ensure (s == Status::eRunning or s == Status::eAborting or s == Status::eCompleted );
443 */
444 nonvirtual void Start () const;
445 nonvirtual void Start (WaitUntilStarted) const;
446
447#if qStroika_Platform_Windows
448 public:
449 /**
450 * CalledInRepThreadAbortProc_ USED TO (until Stroika 2.0a234) - call CheckForThreadInterupption () in most cases. But that appeared to cause some trouble
451 * problably because of Windows library code calling an altertable function without being prepared for it to throw. So we adopted
452 * a safer apporach, and just follow all these alertable calls with CheckForInterruption().
453 *
454 * However, occasionally you use a library (like gsoap) that makes this difficult, so for those cases, enable this throw from APC feature.
455 *
456 * \note Get function CAN be called with *this == nullptr, but
457 * \pre if throwInterruptExceptionInsideUserAPC then *this != nullptr;
458 */
459 nonvirtual bool ThrowInterruptExceptionInsideUserAPC () const noexcept;
460 nonvirtual bool ThrowInterruptExceptionInsideUserAPC (optional<bool> throwInterruptExceptionInsideUserAPC);
461#endif
462
463 public:
464 /**
465 * \brief Abort gracefully shuts down and terminates the given thread (using cooperative multitasking).
466 *
467 * \note Since Stroika v3.0 (and C++20), this is accompished internally via std::stop_token.
468 *
469 * Cancelation works by setting a flag in that thread, which is checked at each 'cancelation point' (plus a little
470 * extra magic).
471 *
472 * This causes the given thread to throw an AbortException whenever it reaches one of these cancelation points
473 * (or if already at one such waitable cancelation point).
474 *
475 * This call is (generally) non-blocking (may block briefly for critical section to update status,
476 * but does NOT block until Stop successful). See AbortAndWaitUntilDone() to abort and wait for completion.
477 *
478 * This can be called on a thread object at any time (reps are internally synrchonized), and in any state (except nullptr, which can only happen in the thread
479 * was created with nullptr/default CTOR and never assigned from Thread::New).
480 *
481 * \note This counts on Stroika's semi-cooperative multitasking (to be safe). This means if you call libraries that don't
482 * check for thread interruption, those threads may not BE interruptible during that region of code.
483 * @see Thread::GetThrowInterruptExceptionInsideUserAPC()
484 *
485 * \note It IS possible to have two DIFFERNT Ptr objects being called in different threads, one doing a Start ()
486 * and the other doing an Abort (); because of this, its allowed to call Start() in the 'aborted' state.
487 *
488 * \pre *this != nullptr
489 */
490 nonvirtual void Abort () const;
491
492 public:
493 /**
494 * \brief Wait for the pointed-to thread to be done. If the thread completed with an exception (other than thread abort exception)
495 * that exception will be re-thrown in the calling thread.
496 *
497 * This API is frequently preferred over WaitForDone () - because you frequently will do work in a thread which when failing - you want
498 * reported somehow. But this is not ALWAYS desirable - like when you have worker threads are just trying to clean up, and don't care that
499 * parts of it may have failed.
500 *
501 * JoinUntil (timeout + Time::GetTickCount ());
502 *
503 * @see WaitForDone ()
504 * @see ThrowIfDoneWithException ()
505 *
506 * \note ***Cancelation Point***
507 *
508 * \pre *this != nullptr
509 */
510 nonvirtual void Join (Time::DurationSeconds timeout = Time::kInfinity) const;
511
512 public:
513 /**
514 * \brief Wait for the pointed-to thread to be done. If the thread completed with an exception (other than thread abort exception)
515 * that exception will be re-thrown in the calling thread.
516 *
517 * This API is frequently preferred over WaitForDone () - because you frequently will do work in a thread which when failing - you want
518 * reported somehow. But this is not ALWAYS desirable - like when you have worker threads are just trying to clean up, and don't care that
519 * parts of it may have failed.
520 *
521 * WaitForDoneUntil () followed up ThrowIfDoneWithException ()
522 *
523 * \note Considered using ThrowIfDoneWithException () always in WaitForDone()
524 * or make optional if existing WAIT API throws child exceptions. Maybe parameter in construction
525 * of the thread?
526 *
527 * Decided against always re-throwing because sometimes you just don't care for a given thread what sort of errors
528 * it had (maybe cuz you've given up on the larger task).
529 *
530 * Decided against encoding that choice in the Thread::New () function (making it a property) and then always doing in WaitForDone () - because
531 * then the the choice would be far away from where the waiting is done - and that Waiting - really needs to be setup to KNOW its likely
532 * to get an exception. So that seemed the wrong place.
533 *
534 * Considered making this just an overload of WaitForDone () - with an extra param - reThrow - and that's really close to what I ended up
535 * with. But overloading would force me to pick a default, which would cause a struggle between backward compatabilitiy and what
536 * I think is the more common case. Or maybe there is no clearly more common case. This name seems fine.
537 *
538 * \note Possible aliases WaitAndThrowAnyChildThreadExceptions, WaitForDoneUntilAndPropagateExceptions ()
539 *
540 * @see WaitForDoneUntil ()
541 * @see ThrowIfDoneWithException ()
542 *
543 * \note ***Cancelation Point***
544 *
545 * \pre *this != nullptr
546 */
547 nonvirtual void JoinUntil (Time::TimePointSeconds timeoutAt) const;
548
549 public:
550 /**
551 * Wait until thread is done (use Abort to request termination) - throws if timeout
552 * Note that its legal to call WaitForDone on a thread in any state (Some may just
553 * have no effect - return quickly).
554 *
555 * @see WaitForDoneUntil (), @see Join
556 *
557 * \note ***Cancelation Point***
558 *
559 * \pre *this != nullptr
560 */
561 nonvirtual void WaitForDone (Time::DurationSeconds timeout = Time::kInfinity) const;
562
563 public:
564 /**
565 * Wait until thread is done (use Abort to request termination) - throws if timeout
566 * Note that its legal to call WaitForDoneUntil on a thread in any state.
567 * Some may just have no effect.
568 *
569 * @see WaitForDone (), @see Join
570 *
571 * \note This does a tiny bit more than waiting for the done state to be set - it also
572 * 'joins' (frees memory for) underlying thread if still allocated. This should not be visible/noticed
573 * except for in a debugger or #if qStroika_Foundation_Execution_Thread_SupportThreadStatistics
574 *
575 * \note ***Cancelation Point***
576 *
577 * \pre *this != nullptr
578 */
579 nonvirtual void WaitForDoneUntil (Time::TimePointSeconds timeoutAt) const;
580
581 public:
582 /**
583 * Wait until thread is done (use Abort to request termination) or timeoutAt expires
584 *
585 * Returns: true if thread done, and false if timeout
586 *
587 * Note that its legal to call WaitForDoneUntilQuietly on a thread in any state - including nullptr.
588 * Some may just have no effect.
589 *
590 * \note This does a tiny bit more than waiting for the done state to be set - it also
591 * 'joins' (frees memory for) underlying thread if still allocated. This should not be visible/noticed
592 * except for in a debugger or #if qStroika_Foundation_Execution_Thread_SupportThreadStatistics
593 *
594 * \note ***Cancelation Point***
595 *
596 * \pre *this != nullptr
597 */
598 nonvirtual bool WaitForDoneUntilQuietly (Time::TimePointSeconds timeoutAt) const;
599
600 public:
601 /**
602 * \brief Abort () the thread, and then WaitForDone () (aka AbortAndWaitForDoneUntil (timeout + GetTickCount))
603 *
604 * \note This frequently (and nearly always in a destructor) - should be preceded by:
605 * \code
606 * Execution::Thread::SuppressInterruptionInContext suppressInterruption; // critical to prohibit this thread from interruption until its killed owned threads
607 * \endcode
608 *
609 * @see AbortAndWaitForDoneUntil ()
610 *
611 * \note ***Cancelation Point***
612 *
613 * \pre *this != nullptr
614 */
615 nonvirtual void AbortAndWaitForDone (Time::DurationSeconds timeout = Time::kInfinity) const;
616
617 public:
618 /**
619 * \brief Abort () the thread, and then WaitForDone ()
620 *
621 * \note ONE Abort () suffices, by design: this waits, and deliberately never re-sends.
622 * Abort () sets a durable interruption flag; the signal (POSIX) or APC (Windows) it also
623 * delivers exists only to break a blocking call already in flight. A thread that fails to
624 * notice a single Abort () is therefore a defect in the interruption mechanism - not
625 * something a caller can legitimately paper over by aborting again, and re-sending would
626 * only hide it. Nor would repeating be harmless: on POSIX the wakeup IS the EINTR, so a
627 * thread shutting down inside third-party code would see a stream of EINTRs it may not
628 * handle. Stroika before v3 did re-send; that was removed on purpose.
629 *
630 * \note Note that its legal to call AbortAndWaitForDone on a thread in any state.
631 * Some may just have no effect
632 *
633 * An example of when this is useful is if you have a thread (performing some operation on
634 * behalf of an object - with data pointers to that object)
635 * and must stop the thread (its no longer useful) - but must assure its done before you
636 * destroy the rest of the data...)
637 * As for example in FileUtils - DirectoryWatcher...
638 *
639 * throws if timeout
640 *
641 * \note This frequently (and nearly always in a destructor) - should be preceded by:
642 * \code
643 * Execution::Thread::SuppressInterruptionInContext suppressInterruption; // critical to prohibit this thread from interruption until its killed owned threads
644 * \endcode
645 *
646 * \note ***Cancelation Point***
647 *
648 * @see Abort ()
649 * @see WaitForDoneUntil ()
650 * @see AbortAndWaitForDone ()
651 *
652 * \pre *this != nullptr
653 */
654 nonvirtual void AbortAndWaitForDoneUntil (Time::TimePointSeconds timeoutAt) const;
655
656 public:
657 /**
658 * If the thread is Done() - and completed with an exception (other than interrupt),
659 * this throws that exception, allowing an exception thrown inside a thread,
660 * to be propagated across threads.
661 *
662 * \note This function intentionally omits InterruptException and AbortException from
663 * this rule, so that if you abort or interrupt a thread and then call this method,
664 * it will not rethrow.
665 *
666 * The reason for this choice is that the interrupt/abort are usually generated externally
667 * and the intent of this method is to pass information back from the thread to the caller.
668 */
669 nonvirtual void ThrowIfDoneWithException () const;
670
671#if qStroika_Platform_Windows
672 public:
673 /**
674 * Look pumping messages until either time2Pump is exceeded or the thread completes.
675 * Its NOT an error if the timeout is exceeded.
676 *
677 * throws if timeout
678 *
679 * @see WaitForDoneUntil ()
680 *
681 * \note ***Cancelation Point***
682 *
683 * \pre *this != nullptr
684 */
685 nonvirtual void WaitForDoneWhilePumpingMessages (Time::DurationSeconds timeout = Time::kInfinity) const;
686#endif
687
688 public:
689 /**
690 * This is a portable wrapper on setting thread priorities. It has fewer knobs than direct or low level
691 * APIs. You can always directly call low-level native APIs using GetNativeHandle().
692 *
693 * \note - no GetPriority API, cuz cannot do something vaguely like that portably. For one thing, priority
694 * is more complex than a single number (like this argument) at runtime for reading on Linux.
695 */
696 nonvirtual void SetThreadPriority (Priority priority = Priority::eNormal) const;
697
698 public:
699 /**
700 * Each Thread object has an associated state. Since this can be accessed from one thread while things
701 * in another thread, by the time the answer is returned, the value may have changed.
702 *
703 * But only certain transitions are legal. Status::eNull is the starting state for SOME Thread constructors (no arg).
704 * Nothing transitions back to the Status:eNull state. From there when you specify a std::function<> to run,
705 * then you transition to Status::eNotYetRunning.
706 *
707 * From eNotYetRunning, you can transition to eRunning with Start () (or the starting thread CTOR). Or you can transition from
708 * eNotYetRunning to eAborting, if you call Abort() before Start().
709 *
710 * From eRunning (or eNotYetRunning) you can transition to eAborting or eCompleted (or from eAborting to eCompleted).
711 *
712 * A thread object can never transition back (by this I mean the underlying pointed to rep - the container of
713 * course can transition back by being assigned another ThreadRep).
714 *
715 * \pre *this != nullptr
716 *
717 * \note - Calling GetStatus () is generally not a good idea, except for debugging purposes. Generally, you will
718 * want to call WaitForDone (), and perhaps Abort, or AbortAndWaitForDone (). GetStatus () gives you a clue
719 * what the thread was doing, but by the time you look it could have changed.
720 */
721 nonvirtual Status GetStatus () const noexcept;
722
723 public:
724 /**
725 * Return true iff WaitForDone () would return immediately;
726 *
727 * \pre not == nullptr
728 *
729 * This will return true iff GetStatus() would return eCompleted.
730 *
731 * Note - some internal traces of the thread object may still be running at this point, but its safe to call join at this point without significant blockage.
732 */
733 nonvirtual bool IsDone () const;
734
735 public:
736 /**
737 * Thread name does NOT need to be unique and defaults to '', but can be used on advisory
738 * basis for debugging. Also - setting the thread name, and then getting it back, may not
739 * produce the same result. Some OSes may munge the name to make it unique, or conform
740 * to some naming convention.
741 *
742 * These names should not be counted on for program logic.
743 *
744 * Thread names appear frequently in debug trace messages.
745 */
746 nonvirtual Characters::String GetThreadName () const;
747
748 public:
749 /**
750 * \pre GetStatus () != Status::eNull
751 *
752 * @see GetThreadName ();
753 */
754 nonvirtual void SetThreadName (const Characters::String& threadName) const;
755
756 public:
757 /**
758 * Return a snapshot of the current stack settings - configured - and dynamic. Much/most of this
759 * may not be available on your system.
760 *
761 * \note @todo - IMPLEMENT ON SOME SYSTEM ;-) Not sure if/where we can do this. Tricky...
762 * \note NYI - see https://github.com/SophistSolutions/Stroika/issues/609 (STK-475)
763 */
764 nonvirtual ConfigurationStatus GetConfigurationStatus () const;
765
766 public:
767 /**
768 * @see Characters::ToString ()
769 */
770 nonvirtual Characters::String ToString () const;
771
772 public:
773 /**
774 */
775 nonvirtual bool operator== (const Ptr& rhs) const;
776 nonvirtual bool operator== (nullptr_t) const;
777
778 public:
779 /**
780 */
781 nonvirtual strong_ordering operator<=> (const Ptr& rhs) const;
782 nonvirtual strong_ordering operator<=> (nullptr_t) const;
783
784 public:
785 /**
786 * \brief return true iff *this != nullptr
787 */
788 nonvirtual explicit operator bool () const;
789
790 private:
791 shared_ptr<Rep_> fRep_;
792 Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE Debug::AssertExternallySynchronizedChecker fThisAssertExternallySynchronized_;
793#if qCompilerAndStdLib_thread_local_static_inline_twice_Buggy
794 static weak_ptr<Rep_>& sCurrentThreadRep_BWA_ ()
795 {
796 static thread_local weak_ptr<Rep_> sCurrentThreadRep_;
797 return sCurrentThreadRep_;
798 }
799#else
800 static inline thread_local weak_ptr<Rep_> sCurrentThreadRep_;
801#endif
802
803 private:
804 friend Ptr New (const function<void ()>& fun2CallOnce, const optional<Characters::String>& name, const optional<Configuration>& configuration);
805 friend Ptr GetCurrent ();
807 friend void CheckForInterruption ();
808 };
809
810 /**
811 * Handy wrapper around a Thread::Ptr, when you want to assure the thread is terminated before the CleanupPtr goes out of scope.
812 */
813 class CleanupPtr : public Ptr {
814 public:
815 /**
816 */
817 enum class AbortFlag {
818 eAbortBeforeWaiting,
819 eDirectlyWait
820 };
821 using AbortFlag::eAbortBeforeWaiting;
822 using AbortFlag::eDirectlyWait;
823
824 public:
825 /**
826 * \brief in destructor, wait for the thread to terminate (optionally aborting it first - depending on CleahupPtr arg/flag)
827 *
828 * \note it is OK to pass a nullptr, or to otherwise stop/abort the thread. This class wraps safe checking around the thread ptr to make sure
829 * it gets cleaned up.
830 */
831 CleanupPtr (const CleanupPtr&) = delete;
832 CleanupPtr (AbortFlag abortFlag, Ptr threadPtr = nullptr);
833
834 public:
835 ~CleanupPtr ();
836
837 public:
838 /**
839 * Assigning a new Thread::Ptr object just replaces the thread that will be 'cleaned up' in the
840 * CleanupPtr destructor. It doesn't force the previous thread to be terminated.
841 */
842 nonvirtual CleanupPtr& operator= (const Ptr&);
843 nonvirtual CleanupPtr& operator= (const CleanupPtr&) = delete;
844
845 private:
846 bool fAbort_{false};
847 };
848
849 /**
850 */
851 class AbortException : public Exception<> {
852 public:
853 AbortException ();
854
855 public:
856 /*
857 * Handy constant you can use to avoid construction.
858 *
859 * Statically allocate because:
860 * o Performance
861 * o Only legal to throw these while main active (so safe to use in that context)
862 * o Avoids issue with re-throwing while constructing one
863 */
864 static const AbortException kThe;
865 };
866 inline const AbortException AbortException::kThe;
867
868 using InterruptException [[deprecated ("Since Stroika v3.0d4 - use AbortException")]] = AbortException;
869
870 /**
871 * Thread IDs tend to be long and not easy to read in trace output. This utility class just maps these long
872 * ids to a short index. Again - ONLY for easier / brevity in logging. But a common registry is maintained here
873 * to allow all the logging across Stroika to use the same shortened IDs.
874 *
875 * Note you can only reference the singleton sThe. This can be referenced before main, or after main safely,
876 * but in those cases, there can be no threads, so it just returns zero (GetIndex).
877 *
878 * NOTE - this class is slightly queer, in that it guarantees behavior of one of its methods BEFORE its
879 * constructed and AFTER its been destroyed. This cannot be 100% true in general and might cause some problems
880 * with sanitizers and the like. But I think this path will generally work and certainly tries to give reasonable
881 * answers when called outside its lifetime (and should work due to only having a single singleton instance).
882 *
883 * \note \em Thread-Safety <a href="Thread-Safety.md#Internally-Synchronized-Thread-Safety">Internally-Synchronized-Thread-Safety</a>
884 */
886 protected:
887 IndexRegistrar (const IndexRegistrar&) = delete;
889
890 public:
892
893 public:
894 nonvirtual IndexRegistrar& operator= (const IndexRegistrar&) = delete;
895
896 public:
897 /**
898 */
899 nonvirtual unsigned int GetIndex (const IDType& threadID, bool* wasNew = nullptr);
900
901 public:
902 /**
903 */
904 static IndexRegistrar sThe;
905
906 private:
907 bool fInitialized_{false};
908 mutex fMutex_; // for read/update the fShownThreadIDs_ map
909 map<IDType, unsigned int> fShownThreadIDs_; // use std::map instead of Stroika to avoid module deadly embrace
910 };
911 inline IndexRegistrar IndexRegistrar::sThe;
912
913 /**
914 * This object - while in existence, blocks delivery of all Thread::AbortException's
915 * (for this thread in which its instantiated). This blocking nest (so if you have two of them in one thread, only when the last
916 * one is destroyed does the block on Interruption be removed).
917 *
918 * This is used to prevent a second abort request coming in to a thread already in the process of shutting down, which
919 * might cause a second, or incomplete cleanup.
920 *
921 * Note - this does NOT prevent the delivery of Windows APC messages, nor POSIX interrupt signals. It just prevents that
922 * from doing anything (other than maybe an EINTR return).
923 *
924 * It might be NICE to have the DTOR be a cancelation point, but that would violate the rule that you cannot throw
925 * from a destructor.
926 *
927 * Any blocked Interrupt Exceptions will wait til the next cancelation point to be invoked (so call
928 * CheckForInterruption to force that). The destructor of this suppress (even when count hits zero)
929 * will not throw.
930 *
931 * \par Example Usage
932 * \code
933 * foo::~foo ()
934 * {
935 * // critical to prohibit this thread from interruption until it completes its cleanup
936 * Thread::SuppressInterruptionInContext suppressAborts;
937 * }
938 * \endcode
939 *
940 */
948
949 /**
950 * No arg- constructor is available for use in applications like thread pools. Also, a variety
951 * of cases, its handy to declare a Thread data member (and init in CTOR), but not
952 * specify what gets run until later.
953 *
954 * After this call, GetStatus () returns Status::eNull
955 *
956 * fun2CallOnce is called precisely once by this thread CTOR, but called in
957 * another thread with the arg 'arg'.
958 *
959 * \note about the 'configuration' parameter. If missing (or parts missing) - the whole are parts from from
960 * the static GetDefaultConfiguration () function. If defaults are missing there too, the OS / system defaults
961 * are relied upon.
962 *
963 * It's not expected one would need to use this often, but when you need it you need it early - before the thread has
964 * been constructed (generally) - or at least before started (sucks swapping stacks out on a running thread ;-))
965 *
966 * \note Unlike std::thread, a Stroika Thread is not started automatically (unless you pass eAutoStart as a constructor argument),
967 * and it can run in the background after the Thread has gone out of scope (std::thread you can do this but must call detach).
968 *
969 * \pre Debug::AppearsDuringMainLifetime() at all points during the threads lifetime. It must be stopped
970 * before Debug::AppearsDuringMainLifetime() becomes untrue. This is somewhat checked by the Stroika
971 * thread infrastructure, but may not be fully reliably asserted (see AllThreadsDeadDetector_)
972 *
973 * \par Example Usage
974 * \code
975 * Thread::New ([r]() { r->Run (); }, Thread::eAutoStart); // runs arg to completion then thread destroyed. New returns once thread created
976 * \endcode
977 *
978 * \par Example Usage
979 * \code
980 * Thread::Ptr t = Thread::New ([r]() { r->Run (); }, Thread::eAutoStart, "Thread Name");
981 * \endcode
982 *
983 * \par Example Usage
984 * \code
985 * Thread::Ptr t = Thread::New ([r]() { r->Run (); });
986 * t.Start ();
987 * t.WaitForDone ();
988 * \endcode
989 */
990 Ptr New (const function<void ()>& fun2CallOnce, const optional<Characters::String>& name, const optional<Configuration>& configuration);
991 Ptr New (const function<void ()>& fun2CallOnce, const Characters::String& name, const optional<Configuration>& configuration = nullopt);
992 Ptr New (const function<void ()>& fun2CallOnce, const optional<Configuration>& configuration = nullopt);
993 Ptr New (const function<void ()>& fun2CallOnce, AutoStartFlag, const optional<Characters::String>& name,
994 const optional<Configuration>& configuration);
995 Ptr New (const function<void ()>& fun2CallOnce, AutoStartFlag, const Characters::String& name,
996 const optional<Configuration>& configuration = nullopt);
997 Ptr New (const function<void ()>& fun2CallOnce, AutoStartFlag, const optional<Configuration>& configuration = nullopt);
998
999 /**
1000 * \pre foreach Thread t: t.GetStatus () == Status::eNotYetRunning
1001 */
1002 void Start (const Traversal::Iterable<Ptr>& threads);
1003
1004 /**
1005 * \brief foreach Thread t: t.Abort ()
1006 *
1007 * \pre foreach Thread t: t != nullptr
1008 *
1009 * \see Thread::Ptr::Abort
1010 */
1011 void Abort (const Traversal::Iterable<Ptr>& threads);
1012
1013 /**
1014 * \note ***Cancelation Point***
1015 *
1016 * \pre foreach Thread t: t != nullptr
1017 */
1018 void WaitForDone (const Traversal::Iterable<Ptr>& threads, Time::DurationSeconds timeout = Time::kInfinity);
1019
1020 /**
1021 * \note ***Cancelation Point***
1022 *
1023 * \pre foreach Thread t: t != nullptr
1024 */
1025 void WaitForDoneUntil (const Traversal::Iterable<Ptr>& threads, Time::TimePointSeconds timeoutAt);
1026
1027 /**
1028 * \brief - shorthand for AbortAndWaitForDoneUntil (Time::GetTickCount () + timeout)
1029 *
1030 * \note ***Cancelation Point***
1031 *
1032 * @see Thread::Ptr::AbortAndWaitForDone
1033 *
1034 * @see Thread::AbortAndWaitForDoneUntil
1035 *
1036 * \note This frequently (and nearly always in a destructor) - should be preceded by:
1037 * \code
1038 * Execution::Thread::SuppressInterruptionInContext suppressInterruption; // critical to prohibit this thread from interruption until its killed owned threads
1039 * \endcode
1040 *
1041 * \pre foreach Thread t: t != nullptr
1042 */
1043 void AbortAndWaitForDone (const Traversal::Iterable<Ptr>& threads, Time::DurationSeconds timeout = Time::kInfinity);
1044
1045 /**
1046 * \note ***Cancelation Point***
1047 *
1048 * @see Thread::Ptr::AbortAndWaitForDoneUntil
1049 *
1050 * \note This frequently (and nearly always in a destructor) - should be preceded by:
1051 * \code
1052 * Execution::Thread::SuppressInterruptionInContext suppressInterruption; // critical to prohibit this thread from interruption until its killed owned threads
1053 * \endcode
1054 *
1055 * \pre foreach Thread t: t != nullptr
1056 */
1058
1059 /**
1060 * Generally should not be reported. It's just to help force a thread to shut itself down
1061 */
1062 class AbortException;
1063
1065
1066#if qStroika_Foundation_Execution_Thread_SupportThreadStatistics
1067 /**
1068 */
1069 struct Statistics {
1070 /**
1071 * These are the thread objects in the status 'running'. It doesn't count ones that exist,
1072 * or Thread objects (which could be null or completed)
1073 */
1074 Traversal::Iterable<IDType> fRunningThreads;
1075 };
1076
1077 /**
1078 * This does not return statistics about this thread (its a static method) - but about all thread allocations (through
1079 * the Stroika thread API).
1080 */
1081 Statistics GetStatistics ();
1082#endif
1083
1084#if qStroika_Platform_POSIX
1085 /**
1086 * Unsafe to change this while threads running - at least if you could be interupting threads during this time.
1087 * If argument given, this resets the signalNumber.
1088 * Either way, this returns the previous value.
1089 */
1090 SignalID SignalUsedForThreadInterrupt () noexcept;
1091 SignalID SignalUsedForThreadInterrupt (optional<SignalID> signalNumber);
1092#endif
1093
1094 struct FormatThreadInfo {
1095 bool fIncludeLeadingZeros{false};
1096 };
1097
1098 /**
1099 * Represent the thread ID for display - typically as an integer.
1100 *
1101 * \note this function is NOT a cancelation point
1102 *
1103 * \note this returns an ASCII string (not using String class library) so easier to use from code expecting no cancelation
1104 *
1105 * @see Characters::ToString (Thread::IDType threadID)
1106 */
1107 wstring FormatThreadID (Thread::IDType threadID, const FormatThreadInfo& formatInfo = {});
1108 string FormatThreadID_A (Thread::IDType threadID, const FormatThreadInfo& formatInfo = {});
1109
1110 /**
1111 */
1112 IDType GetCurrentThreadID () noexcept;
1113
1114 /**
1115 * If the current (calling) thread is a 'Stroika thread' - that thread Ptr is returned. If the current thread is NOT a stroika thread (e.g. the main thread)
1116 * this will return a nullptr.
1117 *
1118 * \note SEE https://github.com/SophistSolutions/Stroika/issues/1126 (STK-994) - for the idea of creating a special Ptr - just for the main thread. But really
1119 * no reason I can see --LGP 2023-10-18
1120 */
1121 Ptr GetCurrent ();
1122
1123#if defined(__cpp_lib_jthread)
1124 /**
1125 */
1126 optional<stop_token> GetCurrentThreadStopToken ();
1127#endif
1128
1129 /**
1130 * Returns true iff it is potentially useful to call CheckForInterruption.
1131 */
1133
1134 /**
1135 * Our thread interruption (and abort) mechanism only throws at certain 'signalable' (alertable/cancelable)
1136 * spots in the code - like sleeps, most reads, etc.
1137 * This function will also trigger a throw if called inside a thread which is being aborted.
1138 *
1139 * Any call to this routine is a 'cancelation point'.
1140 *
1141 * \note ***Cancelation Point***
1142 *
1143 * \note This name is somewhat historical, but still reasonable. But now might be better called CheckForThreadAbort, since thats all it does now.
1144 */
1145 void CheckForInterruption ();
1146
1147 /*
1148 * Avoid interference with Windows SDK headers. I hate needless C macros (with short, common names)
1149 */
1150#ifdef Yield
1151#undef Yield
1152#endif
1153
1154 /**
1155 * \brief calls CheckForInterruption, and std::this_thread::yield ()
1156 *
1157 * \note ***Cancelation Point***
1158 * To avoid cancelation point, directly call std::this_thread::yield ()
1159 */
1160 dont_inline void Yield ();
1161
1162 };
1163
1164}
1165
1166/*
1167 ********************************************************************************
1168 ***************************** Implementation Details ***************************
1169 ********************************************************************************
1170 */
1171#include "Thread.inl"
1172
1173#endif /*_Stroika_Foundation_Execution_Thread_h_*/
#define Stroika_Define_Enum_Bounds(FIRST_ITEM, LAST_ITEM)
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Definition Realtime.h:82
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Definition Realtime.h:57
#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE
[[msvc::no_unique_address]] isn't always broken in MSVC. Annotate with this on things where its not b...
Definition StdCompat.h:481
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
Definition Exceptions.h:219
CleanupPtr(const CleanupPtr &)=delete
in destructor, wait for the thread to terminate (optionally aborting it first - depending on CleahupP...
nonvirtual CleanupPtr & operator=(const Ptr &)
Definition Thread.inl:307
Thread::Ptr is a (unsynchronized) smart pointer referencing an internally synchronized std::thread ob...
Definition Thread.h:357
nonvirtual ConfigurationStatus GetConfigurationStatus() const
friend Ptr New(const function< void()> &fun2CallOnce, const optional< Characters::String > &name, const optional< Configuration > &configuration)
nonvirtual void SetThreadName(const Characters::String &threadName) const
Definition Thread.cpp:627
nonvirtual void Join(Time::DurationSeconds timeout=Time::kInfinity) const
Wait for the pointed-to thread to be done. If the thread completed with an exception (other than thre...
Definition Thread.inl:276
nonvirtual void reset() noexcept
Clear the pointer this Thread smart pointer refers to. This does nothing to affect the state of the u...
Definition Thread.inl:194
nonvirtual void WaitForDoneUntil(Time::TimePointSeconds timeoutAt) const
Definition Thread.cpp:792
nonvirtual void WaitForDone(Time::DurationSeconds timeout=Time::kInfinity) const
Definition Thread.inl:286
nonvirtual void Abort() const
Abort gracefully shuts down and terminates the given thread (using cooperative multitasking).
Definition Thread.cpp:726
nonvirtual bool WaitForDoneUntilQuietly(Time::TimePointSeconds timeoutAt) const
Definition Thread.cpp:800
nonvirtual void JoinUntil(Time::TimePointSeconds timeoutAt) const
Wait for the pointed-to thread to be done. If the thread completed with an exception (other than thre...
Definition Thread.inl:280
nonvirtual void ThrowIfDoneWithException() const
Definition Thread.cpp:780
nonvirtual function< void()> GetFunction() const
Definition Thread.inl:199
nonvirtual NativeHandleType GetNativeHandle() const noexcept
Definition Thread.inl:178
nonvirtual Characters::String ToString() const
Definition Thread.cpp:640
nonvirtual IDType GetID() const
Definition DOM.inl:157
nonvirtual void AbortAndWaitForDone(Time::DurationSeconds timeout=Time::kInfinity) const
Abort () the thread, and then WaitForDone () (aka AbortAndWaitForDoneUntil (timeout + GetTickCount))
Definition Thread.inl:291
nonvirtual void AbortAndWaitForDoneUntil(Time::TimePointSeconds timeoutAt) const
Abort () the thread, and then WaitForDone ()
Definition Thread.cpp:765
nonvirtual Characters::String GetThreadName() const
Definition Thread.cpp:621
nonvirtual Status GetStatus() const noexcept
Definition Thread.inl:255
nonvirtual void SetThreadPriority(Priority priority=Priority::eNormal) const
Definition Thread.cpp:606
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:234
Ptr New(const function< void()> &fun2CallOnce, const optional< Characters::String > &name, const optional< Configuration > &configuration)
Definition Thread.cpp:887
void AbortAndWaitForDoneUntil(const Traversal::Iterable< Ptr > &threads, Time::TimePointSeconds timeoutAt)
Definition Thread.cpp:927
thread::native_handle_type NativeHandleType
Definition Thread.h:245
void Start(const Traversal::Iterable< Ptr > &threads)
Definition Thread.inl:347
wstring FormatThreadID(Thread::IDType threadID, const FormatThreadInfo &formatInfo={})
Definition Thread.cpp:984
void WaitForDone(const Traversal::Iterable< Ptr > &threads, Time::DurationSeconds timeout=Time::kInfinity)
Definition Thread.inl:351
dont_inline void Yield()
calls CheckForInterruption, and std::this_thread::yield ()
Definition Thread.cpp:1111
Configuration DefaultConfiguration() noexcept
Definition Thread.cpp:897
void WaitForDoneUntil(const Traversal::Iterable< Ptr > &threads, Time::TimePointSeconds timeoutAt)
Definition Thread.cpp:940
void Abort(const Traversal::Iterable< Ptr > &threads)
foreach Thread t: t.Abort ()
Definition Thread.cpp:919
void AbortAndWaitForDone(const Traversal::Iterable< Ptr > &threads, Time::DurationSeconds timeout=Time::kInfinity)
shorthand for AbortAndWaitForDoneUntil (Time::GetTickCount () + timeout)
Definition Thread.inl:343
EXPERIMENTAL SUPPORT FOR THREAD STACK (and maybe other) settings.
Definition Thread.h:254