4#include "Stroika/Foundation/Execution/Common.h"
7#if qExecution_WaitableEvent_SupportWaitForMultipleObjects
19 inline void WaitableEvent::WE_::Reset ()
28 inline bool WaitableEvent::WE_::GetIsSet () const noexcept
33 inline bool WaitableEvent::WE_::PeekIsSet () const noexcept
37 inline void WaitableEvent::WE_::Set ()
39 fConditionVariable.MutateDataNotifyAll ([
this] () { fTriggered =
true; });
47 inline WaitableEvent::WaitableEvent ()
51 inline void WaitableEvent::Reset ()
56 inline bool WaitableEvent::GetIsSet () const noexcept
58 return fWE_.GetIsSet ();
60 inline bool WaitableEvent::PeekIsSet () const noexcept
62 return fWE_.PeekIsSet ();
66 fWE_.WaitUntil (timeout + Time::GetTickCount ());
70 return fWE_.WaitUntilQuietly (timeout + Time::GetTickCount ());
74 fWE_.WaitUntil (timeoutAt);
78 return fWE_.WaitUntilQuietly (timeoutAt);
88 WaitUntil (timeoutAt);
92 inline auto WaitableEvent::WaitQuietlyAndReset (
const Time::Duration& timeout) -> WaitStatus
94 auto r = WaitQuietly (timeout);
101 auto r = WaitUntilQuietly (timeoutAt);
106#if qExecution_WaitableEvent_SupportWaitForMultipleObjects
107 template <
typename CONTAINER_OF_WAITABLE_EVENTS,
typename SET_OF_WAITABLE_EVENTS_RESULT>
108 inline SET_OF_WAITABLE_EVENTS_RESULT WaitableEvent::WaitForAny (CONTAINER_OF_WAITABLE_EVENTS waitableEvents, Time::DurationSeconds timeout)
110 return WaitForAnyUntil (waitableEvents, timeout + Time::GetTickCount ());
112 template <
typename ITERATOR_OF_WAITABLE_EVENTS,
typename SET_OF_WAITABLE_EVENTS_RESULT>
113 inline SET_OF_WAITABLE_EVENTS_RESULT WaitableEvent::WaitForAny (ITERATOR_OF_WAITABLE_EVENTS waitableEventsStart,
114 ITERATOR_OF_WAITABLE_EVENTS waitableEventsEnd, Time::DurationSeconds timeout)
116 return WaitForAnyUntil (waitableEventsStart, waitableEventsEnd, timeout + Time::GetTickCount ());
118 template <
typename CONTAINER_OF_WAITABLE_EVENTS,
typename SET_OF_WAITABLE_EVENTS_RESULT>
119 inline SET_OF_WAITABLE_EVENTS_RESULT WaitableEvent::WaitForAnyUntil (CONTAINER_OF_WAITABLE_EVENTS waitableEvents, Time::TimePointSeconds timeoutAt)
121 return WaitForAnyUntil (begin (waitableEvents), end (waitableEvents), timeoutAt);
123 template <
typename ITERATOR_OF_WAITABLE_EVENTS,
typename SET_OF_WAITABLE_EVENTS_RESULT>
124 SET_OF_WAITABLE_EVENTS_RESULT WaitableEvent::WaitForAnyUntil (ITERATOR_OF_WAITABLE_EVENTS waitableEventsStart,
125 ITERATOR_OF_WAITABLE_EVENTS waitableEventsEnd, Time::TimePointSeconds timeoutAt)
127 SET_OF_WAITABLE_EVENTS_RESULT result;
136 shared_ptr<WE_> we = Memory::MakeSharedPtr<WE_> (eAutoReset);
137 [[maybe_unused]]
auto&& cleanup =
Finally ([we, waitableEventsStart, waitableEventsEnd] ()
noexcept {
138 Thread::SuppressInterruptionInContext suppressThreadInterrupts;
139 [[maybe_unused]]
auto&& critSec = lock_guard{sExtraWaitableEventsMutex_};
140 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
141 (*i)->fExtraWaitableEvents_.remove (we);
145 [[maybe_unused]] lock_guard critSec{sExtraWaitableEventsMutex_};
146 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
147 (*i)->fExtraWaitableEvents_.push_front (we);
150 while (result.empty ()) {
151 we->WaitUntil (timeoutAt);
152 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
153 WaitableEvent* we2Test = *i;
154 if (we2Test->fWE_.PeekIsSet ()) {
155 if (we2Test->fWE_.fResetType == eAutoReset) {
156 we2Test->fWE_.Reset ();
158 result.insert (we2Test);
164 template <
typename CONTAINER_OF_WAITABLE_EVENTS>
165 inline void WaitableEvent::WaitForAll (CONTAINER_OF_WAITABLE_EVENTS waitableEvents, Time::DurationSeconds timeout)
167 WaitForAllUntil (waitableEvents, timeout + Time::GetTickCount ());
169 template <
typename ITERATOR_OF_WAITABLE_EVENTS>
170 inline void WaitableEvent::WaitForAll (ITERATOR_OF_WAITABLE_EVENTS waitableEventsStart, ITERATOR_OF_WAITABLE_EVENTS waitableEventsEnd,
171 Time::DurationSeconds timeout)
173 WaitForAllUntil (waitableEventsStart, waitableEventsEnd, timeout + Time::GetTickCount ());
175 template <
typename CONTAINER_OF_WAITABLE_EVENTS>
176 inline void WaitableEvent::WaitForAllUntil (CONTAINER_OF_WAITABLE_EVENTS waitableEvents, Time::TimePointSeconds timeoutAt)
178 WaitForAllUntil (begin (waitableEvents), end (waitableEvents), timeoutAt);
180 template <
typename ITERATOR_OF_WAITABLE_EVENTS>
181 void WaitableEvent::WaitForAllUntil (ITERATOR_OF_WAITABLE_EVENTS waitableEventsStart, ITERATOR_OF_WAITABLE_EVENTS waitableEventsEnd,
182 Time::TimePointSeconds timeoutAt)
192 shared_ptr<WE_> we = Memory::MakeSharedPtr<WE_> (eAutoReset);
193 [[maybe_unused]]
auto&& cleanup =
Finally ([we, waitableEventsStart, waitableEventsEnd] ()
noexcept {
194 Thread::SuppressInterruptionInContext suppressThreadInterrupts;
195 [[maybe_unused]]
auto&& critSec = lock_guard{sExtraWaitableEventsMutex_};
196 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
197 (*i)->fExtraWaitableEvents_.remove (we);
201 [[maybe_unused]] lock_guard critSec{sExtraWaitableEventsMutex_};
202 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
203 (*i)->fExtraWaitableEvents_.push_front (we);
207 we->WaitUntil (timeoutAt);
208 bool anyStillWaiting =
false;
209 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
210 WaitableEvent* we2Test = *i;
212 if (not we2Test->fWE_.PeekIsSet ()) {
213 anyStillWaiting =
true;
216 if (anyStillWaiting) {
220 for (ITERATOR_OF_WAITABLE_EVENTS i = waitableEventsStart; i != waitableEventsEnd; ++i) {
221 WaitableEvent* we2Test = *i;
223 if (we2Test->fWE_.fResetType == eAutoReset) {
224 Assert (we2Test->fWE_.PeekIsSet ());
225 we2Test->fWE_.Reset ();
236 DISABLE_COMPILER_MSC_WARNING_START (4996);
237 DISABLE_COMPILER_GCC_WARNING_START (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
238 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
240 constexpr EnumNames<Execution::WaitableEvent::ResetType> DefaultNames<Execution::WaitableEvent::ResetType>::k{{{
241 {Execution::WaitableEvent::ResetType::eAutoReset, L
"AutoReset"},
242 {Execution::WaitableEvent::ResetType::eManualReset, L
"ManualReset"},
244 DISABLE_COMPILER_MSC_WARNING_END (4996);
245 DISABLE_COMPILER_GCC_WARNING_END (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
246 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
248 constexpr EnumNames<Execution::WaitableEvent::WaitStatus> DefaultNames<Execution::WaitableEvent::WaitStatus>::k{{{
249 {Execution::WaitableEvent::WaitStatus::eTimeout, L
"Timeout"},
250 {Execution::WaitableEvent::WaitStatus::eTriggered, L
"Triggered"},
#define RequireNotNull(p)
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Duration is a chrono::duration<double> (=.
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >
lock_guard< MUTEX > QuickLockType