Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
WaitableEvent.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
7
8#include "Common.h"
9#include "TimeOutException.h"
10
11#include "WaitableEvent.h"
12
13using namespace Stroika::Foundation;
14using namespace Stroika::Foundation::Execution;
15
17
18// Comment this in to turn on aggressive noisy DbgTrace in this module
19//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
20
21/*
22 * Design notes:
23 *
24 * o The use of condition variables is non-obvious. I haven't found good documentation, but
25 * the best I've found would be
26 * https://computing.llnl.gov/tutorials/pthreads/#ConVarOverview
27 *
28 * In particular, on the surface, it looks like the mutex locks in Wait() and signal should prevent things
29 * form working (deadlock). But they apparently do not cause a deadlock because
30 * "pthread_cond_wait() blocks the calling thread until the specified condition is signalled.
31 * This routine should be called while mutex is locked, and it will automatically release the
32 * mutex while it waits. After signal is received and thread is awakened, mutex will be
33 * automatically locked for use by the thread. The programmer is then responsible for
34 * unlocking mutex when the thread is finished with it."
35 *
36 */
37
38/*
39 ********************************************************************************
40 ****************************** WaitableEvent::WE_ ******************************
41 ********************************************************************************
42 */
43void WaitableEvent::WE_::WaitUntil (Time::TimePointSeconds timeoutAt)
44{
45 if (WaitUntilQuietly (timeoutAt) == WaitStatus::eTimeout) {
46// note - safe use of TimeOutException::kThe because you cannot really wait except when threads are running, so
47// inside 'main' lifetime
48#if USE_NOISY_TRACE_IN_THIS_MODULE_
49 // only thing Throw() helper does is DbgTrace ()- and that can make traces hard to read unless you are debugging a timeout /event issue
51#else
53#endif
54 }
55}
56
57auto WaitableEvent::WE_::WaitUntilQuietly (Time::TimePointSeconds timeoutAt) -> WaitStatus
58{
59#if USE_NOISY_TRACE_IN_THIS_MODULE_
60 Debug::TraceContextBumper ctx{L"WaitableEvent::WE_::WaitUntilQuietly", "timeout = {}"_f, timeoutAt};
61#endif
63 unique_lock<mutex> lock{fConditionVariable.fMutex};
64 if (fConditionVariable.wait_until (lock, Time::Pin2SafeSeconds (timeoutAt), [this] () { return fTriggered; })) [[likely]] {
65 return WaitStatus::eTriggered;
66 }
67 else {
68 Assert (timeoutAt <= Time::GetTickCount ()); // otherwise we couldn't have timed out
69 return WaitStatus::eTimeout;
70 }
71}
72
73/*
74 ********************************************************************************
75 ********************************** WaitableEvent *******************************
76 ********************************************************************************
77 */
78DISABLE_COMPILER_MSC_WARNING_START (4996);
79DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
80DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
81constexpr WaitableEvent::ResetType WaitableEvent::eAutoReset;
82constexpr WaitableEvent::ResetType WaitableEvent::eManualReset;
83DISABLE_COMPILER_MSC_WARNING_END (4996);
84DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
85DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
86
87#if qStroika_Foundation_Debug_AssertionsChecked || qStroika_FeatureSupported_Valgrind
89{
90#if qExecution_WaitableEvent_SupportWaitForMultipleObjects
91 Require (fExtraWaitableEvents_.empty ()); // Cannot kill a waitable event while its being waited on by others
92#endif
93}
94#endif
95
97{
98#if USE_NOISY_TRACE_IN_THIS_MODULE_
99 Debug::TraceContextBumper ctx{"WaitableEvent::Set"};
100#endif
101 fWE_.Set ();
102#if qExecution_WaitableEvent_SupportWaitForMultipleObjects
103 [[maybe_unused]] lock_guard critSec{sExtraWaitableEventsMutex_};
104 for (const auto& i : fExtraWaitableEvents_) {
105 i->Set ();
106 }
107#endif
108}
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 Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43