ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
condition.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_threads of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8#if !ALIB_SINGLE_THREADED
9ALIB_EXPORT namespace alib { namespace threads {
10
11
12/// This struct wraps C++ standard library types \c std::mutex and \c std::condition_variable.
13/// It allows one or more threads to sleep until any other thread satisfies a condition and
14/// wakes one or all threads up.
15///
16/// \par Abstract Template Type:
17/// This class is an <em>"abstract template type"</em>, which means that it invokes methods
18/// which are not declared and thus have to be declared by a type that derives from this class.
19/// The derived type needs to pass its own type name to template parameter \p{TDerived}.<br>
20/// With that, this type can cast its <c>this</c>-pointer to that type and access its interface.
21/// The derived type has to provide only one function member:
22///
23/// bool isConditionMet()
24/// \par
25/// This has to return \c true if the condition is fulfilled, otherwise \c false.
26///
27/// \par Acquisition Rules:
28/// Before using one of the overloaded blocking sleep methods
29/// #"WaitForNotification(ALIB_DBG_TAKE_CI)", the object has to be locked by calling #".Acquire".
30/// Such acquirement is guaranteed to be held after the method returns.
31/// \par
32/// A notifying thread has to likewise acquire this object before calling either
33/// #"ReleaseAndNotify" or #"ReleaseAndNotifyAll".
34/// However, as the method names indicate, with the return from the notification call, the
35/// internal mutex is released.
36/// \par
37/// Similar to class #"threads::Lock", nested calls to the method #".Acquire" are not allowed and
38/// constitute undefined behavior.
39///
40/// \par Usage Recipe:
41/// Being an <em>"abstract"</em> type, the class is not designed for direct use.
42/// Instead, a derived type should expose its own, dedicated interface, which replaces
43/// this type's interface.
44/// As a sample, let us look at provided derived type #"threads::Event", which implements
45/// simple event-style waiting in two flavors:
46/// - level-triggered waits that do not clear the internal flag and therefore never miss a
47/// prior notification, and
48/// - explicit edge-triggered waits that first clear the flag and then wait (see
49/// methods named <em>ResetAndWait...</em> below).
50///
51/// The simplest possible use-case of this class is implemented as follows:
52/// - The type has protected inheritance to this struct.
53/// - Protected method #"Event::isConditionMet" is defined, which returns \c true if
54/// the instance was notified.
55/// - This parent struct is made a friend to enable access to the protected method.
56/// - Own interface methods are provided. In this case methods
57/// #"Event::Set", #"Event::SetAll", #"Event::Reset"
58/// and #"Event::Wait(ALIB_DBG_TAKE_)". For edge-triggered semantics, use the
59/// #"Event::ResetAndWait(ALIB_DBG_TAKE_)" overloads.
60/// \par
61/// A more sophisticated but still simple implementation can be reviewed by analyzing the
62/// source of type job-queues in classes #"DedicatedWorker" and
63/// #"ThreadPool".
64/// Its corresponding interface methods are <em>push</em> and <em>pop</em> alike,
65/// which do not resemble too much to the terms wait/notify anymore.
66///
67/// \par Debug-Information:
68/// With debug-builds, several assertions are made to avoid wrong use of the type.
69/// This is implemented by adding the field member #".Dbg".
70/// The output format of assertions should be 'clickable' inside a users' IDE.
71/// The default output string is optimized for
72/// \https{JetBrains CLion,www.jetbrains.com/clion} and can be changed by manipulating
73/// the static field member #"DbgConditionAsserter::ASSERTION_FORMAT;*".
74///
75/// \par Availability
76/// This type is not available if the configuration macro #"ALIB_SINGLE_THREADED" is set.
77///
78/// @see
79/// - Chapter #"alib_manual_appendix_callerinfo" of the General Programmer's Manual.
80/// - For this class, a #"alibtools_debug_helpers_gdb;pretty printer" for the
81/// GNU debugger is provided.
82///
83/// @tparam TDerived The derived type which provides method \b isConditionMet.
84template<typename TDerived>
85struct TCondition {
86 /// The mutex used for locking this instance.
87 std::mutex mutex;
88
89 /// The condition variable used for blocking and notification.
90 std::condition_variable conditionVariable;
91
92 /// Helper to statically casts this object to the derived type.
93 /// @return <c>*this</c> cast to a reference of \p{TDerived}.
94 TDerived& cast() { return static_cast<TDerived&>(*this); }
95
96
97 #if ALIB_DEBUG
98 /// The debug tool instance.
100
101 /// Constructor.
102 /// @param dbgName The name of this instance.<br>
103 /// Available only with debug-builds.
104 /// With release-builds, this type is default
105 /// constructed. Hence, this parameter has to be provided using macro
106 /// #"ALIB_DBG", which prunes the name away.
107 TCondition(const character* dbgName) { Dbg.Name= dbgName; }
108 #else
109 TCondition() = default;
110 #endif
111
112 /// A thread which invokes this method gets registered as the current owner of this object,
113 /// until the same thread releases the ownership invoking #"Release".
114 /// In the case that this object is already owned by another thread, the invoking thread is
115 /// suspended until ownership can be gained.<p>
116 /// Multiple (nested) calls to this method are <b>not supported</b> and constitute
117 /// undefined behavior. In debug-compilations, an #"alib_mod_assert;error is raised".
118 ///
119 /// An instance has to be acquired before invoking any of the notifiy- or wait-methods.
120 /// When return from a notification method, the instance is released.
121 /// With return from a wait method, the instance is still held.
122 ///
123 /// \par Debug Parameter:
124 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
126 #if ALIB_DEBUG
127 Dbg.Assert( Dbg.Owner != Thread::GetCurrent(), ALIB_CALLER, ci,
128 "Acquire: Multiple acquirements of TCondition are forbidden." );
129 #endif
130
131 mutex.lock();
132
133 #if ALIB_DEBUG
134 Dbg.Assert( Dbg.Owner==nullptr, ALIB_CALLER, ci,
135 "Acquire: Owner is (still) set, after std::mutex.lock()." );
136 Dbg.Acq.CI = ci;
137 Dbg.Acq.ActionNo= Dbg.ActionCounter.fetch_add(1);
138 Dbg.Owner = Thread::Get(ci.ThreadID);
139 #endif
140 }
141
142 /// Releases ownership of this object.
143 /// If this method is invoked on an object that is not acquired or acquired by a different
144 /// thread, in debug-compilations an #"alib_mod_assert;error is raised".
145 /// In release compilations, this leads to undefined behavior.
146 /// @see Method #".Acquire".
147 /// \par Debug Parameter:
148 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
150 #if ALIB_DEBUG
151 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci, "Release: Not acquired." );
152 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
153 "Release: Ownership is with a different thread" );
154 Dbg.Rel.CI = ci;
155 Dbg.Rel.ActionNo= Dbg.ActionCounter.fetch_add(1);
156 Dbg.Owner= nullptr;
157 #endif
158
159 mutex.unlock();
160 }
161
162 /// Unblock a next waiting thread.<p>
163 /// As the method name indicates, with this implementation, it is necessary to acquire this
164 /// object before invoking this method.
165 /// Internally, the mutex will be released, and thus no separate call to #"Release" is necessary,
166 /// respectively allowed.
167 ///
168 /// \par Debug Parameter:
169 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
171 #if ALIB_DEBUG
172 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
173 "ReleaseAndNotify called without prior acquisition" );
174
175 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
176 "ReleaseAndNotify: Ownership is with a different thread" );
177
178 Dbg.Owner= nullptr;
179 Dbg.Notify.CI = ci;
180 Dbg.Notify.ActionNo= Dbg.ActionCounter.fetch_add(1);
181
182 Dbg.Owner= nullptr;
183 #endif
184
185 mutex.unlock();
186 conditionVariable.notify_one();
187 }
188
189 /// Releases the internal mutex and wakes up all sleeping threads.
190 /// \par Debug Parameter:
191 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
193 #if ALIB_DEBUG
194 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter), ALIB_CALLER, ci,
195 "An exclusive waiter is set. Thus, notifying 'all' is not allowed.");
196
197 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
198 "ReleaseAndNotify called without prior acquisition" );
199
200 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
201 "ReleaseAndNotify: Ownership is with a different thread" );
202
203 Dbg.Owner= nullptr;
204 Dbg.Notify.CI = ci;
205 Dbg.Notify.ActionNo= Dbg.ActionCounter.fetch_add(1);
206 #endif
207
208 mutex.unlock();
209 conditionVariable.notify_all();
210 }
211
212 /// Waits for notification (for an unlimited time).<br>
213 /// Before invoking this method, this object has to be #"TCondition::Acquire;acquired".
214 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
215 /// released by the owner.<br>
216 /// It is allowed to create (endless) loops that never actively release this instance
217 /// but call one of the waiting methods instead.<br>
218 /// Note that "spurious wake-ups" are internally caught with this implementation.
219 /// \par Debug Parameter:
220 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
222 #if ALIB_DEBUG
223 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter)
224 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
225 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
226
227 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
228 "WaitForNotification called without prior acquisition" );
229
230 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
231 "WaitForNotification: Ownership is with a different thread" );
232
233 ++Dbg.CntWaiters;
234 Dbg.Wait.CI = ci;
235 Dbg.Wait.ActionNo= Dbg.ActionCounter.fetch_add(1);
236 Dbg.Owner= nullptr;
237 #endif
238
239 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
240 conditionVariable.wait( lock, [this]{ return cast().isConditionMet(); } );
241 lock.release();
242
243 #if ALIB_DEBUG
244 Dbg.Owner= Thread::Get(ci.ThreadID);
245 --Dbg.CntWaiters;
246 #endif
247 }
248
249 #if !ALIB_DEBUG
250 void WaitForNotification( const Ticks::Duration::TDuration& maxWaitTimeSpan)
251 {
252 #else
253 /// Same as #"WaitForNotification(ALIB_DBG_TAKE_CI)", but takes a C++ time span that defines
254 /// a maximum wait time.
255 ///
256 /// @param maxWaitTimeSpan The maximum time to wait.
257 /// @param ci Caller information.
258 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
259 void WaitForNotification( const Ticks::Duration::TDuration& maxWaitTimeSpan,
260 const CallerInfo& ci ) {
261 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter)
262 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
263 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
264
265 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
266 "WaitForNotification called without prior acquisition" );
267
268 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
269 "WaitForNotification: Ownership is with a different thread" );
270
271 ++Dbg.CntWaiters;
272 Dbg.Wait.CI = ci;
273 Dbg.Wait.ActionNo= Dbg.ActionCounter.fetch_add(1);
274 Dbg.Owner= nullptr;
275 #endif
276
277 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
278 conditionVariable.wait_for( lock, maxWaitTimeSpan, [this]{ return cast().isConditionMet(); } );
279 lock.release();
280
281 #if ALIB_DEBUG
282 Dbg.Owner= Thread::Get(ci.ThreadID);
283 --Dbg.CntWaiters;
284 #endif
285 }
286
287 #if ALIB_DEBUG
288 /// Same as #"WaitForNotification(ALIB_DBG_TAKE_CI)", but takes a time span that defines
289 /// a maximum wait time.
290 ///
291 /// @param maxWaitTimeSpan The maximum time to wait.
292 /// @param ci Caller information.
293 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
294 void WaitForNotification( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
295 { WaitForNotification( maxWaitTimeSpan.Export(), ci ); }
296 #else
297 void WaitForNotification( const Ticks::Duration& maxWaitTimeSpan )
298 { WaitForNotification( maxWaitTimeSpan.Export() ); }
299 #endif
300
301
302 #if !ALIB_DEBUG
303 void WaitForNotification( const Ticks& wakeUpTime )
304 {
305 #else
306 /// Same as #"WaitForNotification(ALIB_DBG_TAKE_CI)", but takes a point in time at which
307 /// waiting stops.
308 ///
309 /// @param wakeUpTime The point in time to wake up, even if not notified.
310 /// @param ci Caller information.
311 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
312 void WaitForNotification( const Ticks& wakeUpTime, const CallerInfo& ci ) {
313 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter)
314 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
315 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
316
317 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
318 "WaitForNotification called without prior acquisition" );
319
320 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
321 "WaitForNotification: Ownership is with a different thread" );
322
323
324 ++Dbg.CntWaiters;
325 Dbg.Wait.CI = ci;
326 Dbg.Wait.ActionNo= Dbg.ActionCounter.fetch_add(1);
327 Dbg.Owner= nullptr;
328 #endif
329
330 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
331 conditionVariable.wait_until( lock, wakeUpTime.Export(),
332 [this]{ return cast().isConditionMet(); } );
333 lock.release();
334
335 #if ALIB_DEBUG
336 Dbg.Owner= Thread::Get(ci.ThreadID);
337 --Dbg.CntWaiters;
338 #endif
339 }
340};
341
342/// Extends <em>"abstract template type"</em> #"TCondition".
343/// This implementation constitutes the simplest possible derivate, by
344/// 1. holding just a boolean member, and
345/// 2. by providing a similar generic interface.
346/// @see Chapter #"alib_manual_appendix_callerinfo" of the General Programmer's Manual.
347class Event : protected TCondition<Event> {
348 #if !DOXYGEN
349 // The parent type needs to be able to call protected method #".isConditionMet".
350 friend struct TCondition<Event>;
351 #endif
352
353 protected:
354 /// Boolean member which records notifications. Defaults to not-notified.
355 bool notified = false;
356
357 /// In general, derivates of #"TCondition" have to return \c true if the former
358 /// reason for blocking a thread is now fulfilled.
359 ///
360 /// @return This implementation returns the value of field member #".notified".
361 bool isConditionMet() { return notified; }
362
363 public:
364 using TCondition<Event>::Acquire;
365 using TCondition<Event>::Release;
366
367 //################################################################################################
368 //### Debug implementation
369 //################################################################################################
370 #if ALIB_DEBUG
371 /// Defaulted default constructor.
372 /// @param dbgName A name for the condition. Only available with debug-compilations.
373 Event(const character* dbgName) : TCondition(dbgName) {}
374 #else
375 Event() = default;
376 #endif
377
378 /// Sets the condition (flag becomes true) and wakes up the next sleeping thread.
379 /// \par Debug Parameter:
380 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
382 Acquire(ALIB_DBG(ci));
383 notified= true;
385 }
386
387 /// Sets the condition (flag becomes true) and wakes up all sleeping threads.
388 /// \par Debug Parameter:
389 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
391 Acquire(ALIB_DBG(ci));
392 notified= true;
394 }
395
396 /// Resets the condition (flag becomes false). No notification is sent.
397 /// \par Debug Parameter:
398 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
400 Acquire(ALIB_DBG(ci));
401 notified= false;
402 Release(ALIB_DBG(ci));
403 }
404
405 /// Waits until the condition is set (for an unlimited time).
406 /// This method does not modify the condition state.
407 /// \par Debug Parameter:
408 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
410 #if ALIB_DEBUG
411 Acquire(ci);
413 Release(ci);
414 #else
417 #endif
418 }
419
420 /// Clears the condition first and then waits (for an unlimited time).
421 /// This provides edge-triggered semantics comparable to the previous implementation of Wait.
422 /// \par Debug Parameter:
423 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
425 #if ALIB_DEBUG
426 Acquire(ci);
427 notified= false;
429 Release(ci);
430 #else
432 notified= false;
434 #endif
435 }
436
437 #if ALIB_DEBUG
438 /// Same as #".Wait(const Ticks::Duration&, const CallerInfo&)", but only up to a given
439 /// duration. This method does not modify the condition state.
440 /// @param maxWaitTimeSpan The maximum time to wait.
441 /// @param ci Caller information.
442 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
443 void Wait( const Ticks::Duration::TDuration& maxWaitTimeSpan, const CallerInfo& ci ) {
444 Acquire(ci);
445 WaitForNotification(maxWaitTimeSpan, ci);
446 Release(ci);
447 }
448
449 /// Clears the condition first and then waits for up to a given duration.
450 /// @param maxWaitTimeSpan The maximum time to wait.
451 /// @param ci Caller information.
452 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
453 void ResetAndWait( const Ticks::Duration::TDuration& maxWaitTimeSpan, const CallerInfo& ci ) {
454 Acquire(ci);
455 notified= false;
456 WaitForNotification(maxWaitTimeSpan, ci);
457 Release(ci);
458 }
459 #else
460 void Wait( const Ticks::Duration::TDuration& maxWaitTimeSpan )
461 {ALIB_LOCK
462 WaitForNotification(maxWaitTimeSpan);
463 }
464
465 void ResetAndWait( const Ticks::Duration::TDuration& maxWaitTimeSpan )
466 {ALIB_LOCK
467 notified= false;
468 WaitForNotification(maxWaitTimeSpan);
469 }
470 #endif
471
472
473 #if ALIB_DEBUG
474 /// Waits for notification but only for a given duration.
475 ///
476 /// Before invoking this method, this object has to be #"TCondition::Acquire;acquired".
477 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
478 /// released later.
479 /// @param maxWaitTimeSpan The maximum time to wait.
480 /// @param ci Caller information.
481 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
482 void Wait( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
483 { Wait( maxWaitTimeSpan.Export(), ci ); }
484
485 /// Clears the condition first and then waits for up to a given duration.
486 /// @param maxWaitTimeSpan The maximum time to wait.
487 /// @param ci Caller information.
488 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
489 void ResetAndWait( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
490 { ResetAndWait( maxWaitTimeSpan.Export(), ci ); }
491 #else
492 void Wait( const Ticks::Duration& maxWaitTimeSpan )
493 { Wait( maxWaitTimeSpan.Export() ); }
494
495 void ResetAndWait( const Ticks::Duration& maxWaitTimeSpan )
496 { ResetAndWait( maxWaitTimeSpan.Export() ); }
497 #endif
498
499 #if ALIB_DEBUG
500 /// Waits for notification, but only until a given point in time.
501 ///
502 /// Before invoking this method, this object has to be #"TCondition::Acquire;acquired".
503 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
504 /// released later.
505 ///
506 /// @param wakeUpTime The point in time to wake up, even if not notified.
507 /// @param ci Caller information.
508 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
509 /// Waits until the condition is set, but only until a given point in time.
510 /// This method does not modify the condition state.
511 void Wait( const Ticks& wakeUpTime, const CallerInfo& ci ) {
512 Acquire(ci);
513 WaitForNotification(wakeUpTime, ci);
514 Release(ci);
515 }
516
517 /// Clears the condition first and then waits until a given point in time.
518 /// @param wakeUpTime The point in time to wake up, even if not notified.
519 /// @param ci Caller information.
520 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
521 void ResetAndWait( const Ticks& wakeUpTime, const CallerInfo& ci ) {
522 Acquire(ci);
523 notified= false;
524 WaitForNotification(wakeUpTime, ci);
525 Release(ci);
526 }
527 #else
528 void Wait( const Ticks& wakeUpTime )
529 {ALIB_LOCK
530 WaitForNotification(wakeUpTime);
531 }
532
533 void ResetAndWait( const Ticks& wakeUpTime )
534 {ALIB_LOCK
535 notified= false;
536 WaitForNotification(wakeUpTime);
537 }
538 #endif
539};
540
541} // namespace alib[threads]
542
543/// Type alias in namespace #"%alib".
544template<typename T= bool>
546
547/// Type alias in namespace #"%alib".
549
550} // namespace [alib]
551
552
553#endif // !ALIB_SINGLE_THREADED
#define ALIB_DBG_TAKE_CI
#define ALIB_CALLER
#define ALIB_EXPORT
#define ALIB_LOCK
#define ALIB_DBG(...)
void SetAll(ALIB_DBG_TAKE_CI)
void Reset(ALIB_DBG_TAKE_CI)
bool notified
Boolean member which records notifications. Defaults to not-notified.
void ResetAndWait(const Ticks::Duration::TDuration &maxWaitTimeSpan, const CallerInfo &ci)
void ResetAndWait(const Ticks &wakeUpTime, const CallerInfo &ci)
void Set(ALIB_DBG_TAKE_CI)
void Wait(const Ticks &wakeUpTime, const CallerInfo &ci)
void ResetAndWait(const Ticks::Duration &maxWaitTimeSpan, const CallerInfo &ci)
void Wait(ALIB_DBG_TAKE_CI)
void Wait(const Ticks::Duration::TDuration &maxWaitTimeSpan, const CallerInfo &ci)
Event(const character *dbgName)
void ResetAndWait(ALIB_DBG_TAKE_CI)
void Wait(const Ticks::Duration &maxWaitTimeSpan, const CallerInfo &ci)
static Thread * GetCurrent()
Definition thread.hpp:294
static Thread * Get(std::thread::id nativeID)
Definition thread.cpp:253
TTimePoint Export() const
constexpr bool IsNull(const T &t)
Definition tmp.hpp:48
constexpr bool IsNotNull(const T &t)
Definition tmp.hpp:55
Definition alox.cpp:14
threads::TCondition< T > TCondition
Type alias in namespace #"%alib".
threads::Event Event
Type alias in namespace #"%alib".
lang::CallerInfo CallerInfo
Type alias in namespace #"%alib".
time::Ticks Ticks
Type alias in namespace #"%alib".
Definition ticks.hpp:86
characters::character character
Type alias in namespace #"%alib".
std::thread::id ThreadID
The ID of the calling thread.
DbgConditionAsserter Dbg
Definition condition.hpp:99
void WaitForNotification(ALIB_DBG_TAKE_CI)
void ReleaseAndNotifyAll(ALIB_DBG_TAKE_CI)
void WaitForNotification(const Ticks &wakeUpTime, const CallerInfo &ci)
TCondition(const character *dbgName)
std::condition_variable conditionVariable
Definition condition.hpp:90
void Release(ALIB_DBG_TAKE_CI)
void Acquire(ALIB_DBG_TAKE_CI)
void WaitForNotification(const Ticks::Duration &maxWaitTimeSpan, const CallerInfo &ci)
void WaitForNotification(const Ticks::Duration::TDuration &maxWaitTimeSpan, const CallerInfo &ci)
void ReleaseAndNotify(ALIB_DBG_TAKE_CI)