Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
WaitableEvent.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
7
8#include "Stroika/Foundation/Execution/Common.h"
9
10#include "WaitableEvent.h"
11
12using namespace Stroika::Foundation;
13using namespace Stroika::Foundation::Execution;
14
16
17// Comment this in to turn on aggressive noisy DbgTrace in this module
18//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
19
20/*
21 * Design notes:
22 *
23 * o The use of condition variables is non-obvious. I haven't found good documentation, but
24 * the best I've found would be
25 * https://computing.llnl.gov/tutorials/pthreads/#ConVarOverview
26 *
27 * In particular, on the surface, it looks like the mutex locks in Wait() and signal should prevent things
28 * form working (deadlock). But they apparently do not cause a deadlock because
29 * "pthread_cond_wait() blocks the calling thread until the specified condition is signalled.
30 * This routine should be called while mutex is locked, and it will automatically release the
31 * mutex while it waits. After signal is received and thread is awakened, mutex will be
32 * automatically locked for use by the thread. The programmer is then responsible for
33 * unlocking mutex when the thread is finished with it."
34 *
35 */
36
37/*
38 ********************************************************************************
39 ****************************** WaitableEvent::WE_ ******************************
40 ********************************************************************************
41 */
42void WaitableEvent::WE_::WaitUntil (Time::TimePointSeconds timeoutAt)
43{
44 if (WaitUntilQuietly (timeoutAt) == WaitStatus::eTimeout) {
45#if USE_NOISY_TRACE_IN_THIS_MODULE_
46 ThrowError (errc::timed_out);
47#else
48 // deliberately NOT ThrowError (): that funnels through Throw (), whose only added value is a DbgTrace ()
49 // which makes traces here hard to read unless you are debugging a timeout/event issue.
50 // Identical exception object, just no trace - keep the two in sync.
51 throw SystemErrorException{make_error_code (errc::timed_out)};
52#endif
53 }
54}
55
56auto WaitableEvent::WE_::WaitUntilQuietly (Time::TimePointSeconds timeoutAt) -> WaitStatus
57{
58#if USE_NOISY_TRACE_IN_THIS_MODULE_
59 Debug::TraceContextBumper ctx{L"WaitableEvent::WE_::WaitUntilQuietly", "timeout = {}"_f, timeoutAt};
60#endif
62 unique_lock<mutex> lock{fConditionVariable.fMutex};
63 if (fConditionVariable.wait_until (lock, Time::Pin2SafeSeconds (timeoutAt), [this] () { return fTriggered; })) [[likely]] {
64 return WaitStatus::eTriggered;
65 }
66 else {
67 Assert (timeoutAt <= Time::GetTickCount ()); // otherwise we couldn't have timed out
68 return WaitStatus::eTimeout;
69 }
70}
71
72/*
73 ********************************************************************************
74 ********************************** WaitableEvent *******************************
75 ********************************************************************************
76 */
77DISABLE_COMPILER_MSC_WARNING_START (4996);
78DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
79DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
80constexpr WaitableEvent::ResetType WaitableEvent::eAutoReset;
81constexpr WaitableEvent::ResetType WaitableEvent::eManualReset;
82DISABLE_COMPILER_MSC_WARNING_END (4996);
83DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
84DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
85
86#if qStroika_Foundation_Debug_AssertionsChecked
88{
89#if qStroika_Foundation_Execution_WaitableEvent_SupportWaitForMultipleObjects
90 Require (fExtraWaitableEvents_.empty ()); // Cannot kill a waitable event while its being waited on by others
91#endif
92}
93#endif
94
96{
97#if USE_NOISY_TRACE_IN_THIS_MODULE_
98 Debug::TraceContextBumper ctx{"WaitableEvent::Set"};
99#endif
100 fWE_.Set ();
101#if qStroika_Foundation_Execution_WaitableEvent_SupportWaitForMultipleObjects
102 [[maybe_unused]] lock_guard critSec{sExtraWaitableEventsMutex_};
103 for (const auto& i : fExtraWaitableEvents_) {
104 i->Set ();
105 }
106#endif
107}
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
Duration is a chrono::duration<double> (=.
Definition Duration.h:96
void ThrowError(error_code ec)
throw a SystemErrorException with the given error_code - or std::bad_alloc for errc::not_enough_memor...