ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
condition.inl
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/// \emoji :copyright: 2013-2025 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>
86{
87 /// The mutex used for locking this instance.
88 std::mutex mutex;
89
90 /// The condition variable used for blocking and notification.
91 std::condition_variable conditionVariable;
92
93 /// Helper to statically casts this object to the derived type.
94 /// @return <c>*this</c> cast to a reference of \p{TDerived}.
95 TDerived& cast() { return static_cast<TDerived&>(*this); }
96
97
98 #if ALIB_DEBUG
99 /// The debug tool instance.
101
102 /// Constructor.
103 /// @param dbgName The name of this instance.<br>
104 /// Available only with debug-builds.
105 /// With release-builds, this type is default
106 /// constructed. Hence, this parameter has to be provided using macro
107 /// #"ALIB_DBG", which prunes the name away.
108 TCondition(const character* dbgName) { Dbg.Name= dbgName; }
109 #else
110 TCondition() = default;
111 #endif
112
113 /// A thread which invokes this method gets registered as the current owner of this object,
114 /// until the same thread releases the ownership invoking #"Release".
115 /// In the case that this object is already owned by another thread, the invoking thread is
116 /// suspended until ownership can be gained.<p>
117 /// Multiple (nested) calls to this method are <b>not supported</b> and constitute
118 /// undefined behavior. In debug-compilations, an #"alib_mod_assert;error is raised".
119 ///
120 /// An instance has to be acquired before invoking any of the notifiy- or wait-methods.
121 /// When return from a notification method, the instance is released.
122 /// With return from a wait method, the instance is still held.
123 ///
124 /// \par Debug Parameter:
125 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
127 #if ALIB_DEBUG
128 Dbg.Assert( Dbg.Owner != Thread::GetCurrent(), ALIB_CALLER, ci,
129 "Acquire: Multiple acquirements of TCondition are forbidden." );
130 #endif
131
132 mutex.lock();
133
134 #if ALIB_DEBUG
135 Dbg.Assert( Dbg.Owner==nullptr, ALIB_CALLER, ci,
136 "Acquire: Owner is (still) set, after std::mutex.lock()." );
137 Dbg.AcqCI = ci;
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.RelCI = ci;
155 Dbg.Owner= nullptr;
156 #endif
157
158 mutex.unlock();
159 }
160
161 /// Unblock a next waiting thread.<p>
162 /// As the method name indicates, with this implementation, it is necessary to acquire this
163 /// object before invoking this method.
164 /// Internally, the mutex will be released, and thus no separate call to #"Release" is necessary,
165 /// respectively allowed.
166 ///
167 /// \par Debug Parameter:
168 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
170 #if ALIB_DEBUG
171 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
172 "ReleaseAndNotify called without prior acquisition" );
173
174 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
175 "ReleaseAndNotify: Ownership is with a different thread" );
176
177 Dbg.Owner= nullptr;
178 Dbg.NotifyCI= ci;
179 Dbg.Owner= nullptr;
180 #endif
181
182 mutex.unlock();
183 conditionVariable.notify_one();
184 }
185
186 /// Releases the internal mutex and wakes up all sleeping threads.
187 /// \par Debug Parameter:
188 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
190 #if ALIB_DEBUG
191 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter), ALIB_CALLER, ci,
192 "An exclusive waiter is set. Thus, notifying 'all' is not allowed.");
193
194 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
195 "ReleaseAndNotify called without prior acquisition" );
196
197 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
198 "ReleaseAndNotify: Ownership is with a different thread" );
199
200 Dbg.Owner= nullptr;
201 Dbg.NotifyCI= ci;
202 #endif
203
204 mutex.unlock();
205 conditionVariable.notify_all();
206 }
207
208 /// Waits for notification (for an unlimited time).<br>
209 /// Before invoking this method, this object has to be #"TCondition::Acquire;acquired".
210 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
211 /// released by the owner.<br>
212 /// It is allowed to create (endless) loops that never actively release this instance
213 /// but call one of the waiting methods instead.<br>
214 /// Note that "spurious wake-ups" are internally caught with this implementation.
215 /// \par Debug Parameter:
216 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
218 #if ALIB_DEBUG
219 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter)
220 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
221 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
222
223 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
224 "WaitForNotification called without prior acquisition" );
225
226 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
227 "WaitForNotification: Ownership is with a different thread" );
228
229 ++Dbg.CntWaiters;
230 Dbg.WaitCI= ci;
231 Dbg.Owner= nullptr;
232 #endif
233
234 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
235 conditionVariable.wait( lock, [this]{ return cast().isConditionMet(); } );
236 lock.release();
237
238 #if ALIB_DEBUG
239 Dbg.Owner= Thread::Get(ci.ThreadID);
240 --Dbg.CntWaiters;
241 #endif
242 }
243
244 #if !ALIB_DEBUG
245 void WaitForNotification( const Ticks::Duration::TDuration& maxWaitTimeSpan)
246 {
247 #else
248 /// Same as #"WaitForNotification(ALIB_DBG_TAKE_CI)", but takes a C++ time span that defines
249 /// a maximum wait time.
250 ///
251 /// @param maxWaitTimeSpan The maximum time to wait.
252 /// @param ci Caller information.
253 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
254 void WaitForNotification( const Ticks::Duration::TDuration& maxWaitTimeSpan,
255 const CallerInfo& ci ) {
256 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter)
257 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
258 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
259
260 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
261 "WaitForNotification called without prior acquisition" );
262
263 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
264 "WaitForNotification: Ownership is with a different thread" );
265
266 ++Dbg.CntWaiters;
267 Dbg.WaitCI= ci;
268 Dbg.Owner= nullptr;
269 #endif
270
271 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
272 conditionVariable.wait_for( lock, maxWaitTimeSpan, [this]{ return cast().isConditionMet(); } );
273 lock.release();
274
275 #if ALIB_DEBUG
276 Dbg.Owner= Thread::Get(ci.ThreadID);
277 --Dbg.CntWaiters;
278 #endif
279 }
280
281 #if ALIB_DEBUG
282 /// Same as #"WaitForNotification(ALIB_DBG_TAKE_CI)", but takes a time span that defines
283 /// a maximum wait time.
284 ///
285 /// @param maxWaitTimeSpan The maximum time to wait.
286 /// @param ci Caller information.
287 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
288 void WaitForNotification( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
289 { WaitForNotification( maxWaitTimeSpan.Export(), ci ); }
290 #else
291 void WaitForNotification( const Ticks::Duration& maxWaitTimeSpan )
292 { WaitForNotification( maxWaitTimeSpan.Export() ); }
293 #endif
294
295
296 #if !ALIB_DEBUG
297 void WaitForNotification( const Ticks& wakeUpTime )
298 {
299 #else
300 /// Same as #"WaitForNotification(ALIB_DBG_TAKE_CI)", but takes a point in time at which
301 /// waiting stops.
302 ///
303 /// @param wakeUpTime The point in time to wake up, even if not notified.
304 /// @param ci Caller information.
305 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
306 void WaitForNotification( const Ticks& wakeUpTime, const CallerInfo& ci ) {
307 Dbg.Assert( lang::IsNull(Dbg.AssertExclusiveWaiter)
308 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
309 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
310
311 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci,
312 "WaitForNotification called without prior acquisition" );
313
314 Dbg.Assert( Dbg.Owner == Thread::GetCurrent(), ALIB_CALLER, ci,
315 "WaitForNotification: Ownership is with a different thread" );
316
317
318 ++Dbg.CntWaiters;
319 Dbg.WaitCI= ci;
320 Dbg.Owner= nullptr;
321 #endif
322
323 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
324 conditionVariable.wait_until( lock, wakeUpTime.Export(),
325 [this]{ return cast().isConditionMet(); } );
326 lock.release();
327
328 #if ALIB_DEBUG
329 Dbg.Owner= Thread::Get(ci.ThreadID);
330 --Dbg.CntWaiters;
331 #endif
332 }
333};
334
335/// Extends <em>"abstract template type"</em> #"TCondition".
336/// This implementation constitutes the simplest possible derivate, by
337/// 1. holding just a boolean member, and
338/// 2. by providing a similar generic interface.
339/// @see Chapter #"alib_manual_appendix_callerinfo" of the General Programmer's Manual.
340class Event : protected TCondition<Event>
341{
342 #if !DOXYGEN
343 // The parent type needs to be able to call protected method #".isConditionMet".
344 friend struct TCondition<Event>;
345 #endif
346
347 protected:
348 /// Boolean member which records notifications. Defaults to not-notified.
349 bool notified = false;
350
351 /// In general, derivates of #"TCondition" have to return \c true if the former
352 /// reason for blocking a thread is now fulfilled.
353 ///
354 /// @return This implementation returns the value of field member #notified.
355 bool isConditionMet() { return notified; }
356
357 public:
358 using TCondition<Event>::Acquire;
359 using TCondition<Event>::Release;
360
361 //################################################################################################
362 //### Debug implementation
363 //################################################################################################
364 #if ALIB_DEBUG
365 /// Defaulted default constructor.
366 /// @param dbgName A name for the condition. Only available with debug-compilations.
367 Event(const character* dbgName) : TCondition(dbgName) {}
368 #else
369 Event() = default;
370 #endif
371
372 /// Sets the condition (flag becomes true) and wakes up the next sleeping thread.
373 /// \par Debug Parameter:
374 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
376 Acquire(ALIB_DBG(ci));
377 notified= true;
379 }
380
381 /// Sets the condition (flag becomes true) and wakes up all sleeping threads.
382 /// \par Debug Parameter:
383 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
385 Acquire(ALIB_DBG(ci));
386 notified= true;
388 }
389
390 /// Resets the condition (flag becomes false). No notification is sent.
391 /// \par Debug Parameter:
392 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
394 Acquire(ALIB_DBG(ci));
395 notified= false;
396 Release(ALIB_DBG(ci));
397 }
398
399 /// Waits until the condition is set (for an unlimited time).
400 /// This method does not modify the condition state.
401 /// \par Debug Parameter:
402 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
404 #if ALIB_DEBUG
405 Acquire(ci);
407 Release(ci);
408 #else
411 #endif
412 }
413
414 /// Clears the condition first and then waits (for an unlimited time).
415 /// This provides edge-triggered semantics comparable to the previous implementation of Wait.
416 /// \par Debug Parameter:
417 /// Pass macro #"ALIB_CALLER_PRUNED" with invocations.
419 #if ALIB_DEBUG
420 Acquire(ci);
421 notified= false;
423 Release(ci);
424 #else
426 notified= false;
428 #endif
429 }
430
431 #if ALIB_DEBUG
432 /// Same as #Wait(const Ticks::Duration&, const CallerInfo&), but only up to a given duration.
433 /// This method does not modify the condition state.
434 /// @param maxWaitTimeSpan The maximum time to wait.
435 /// @param ci Caller information.
436 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
437 void Wait( const Ticks::Duration::TDuration& maxWaitTimeSpan, const CallerInfo& ci ) {
438 Acquire(ci);
439 WaitForNotification(maxWaitTimeSpan, ci);
440 Release(ci);
441 }
442
443 /// Clears the condition first and then waits for up to a given duration.
444 /// @param maxWaitTimeSpan The maximum time to wait.
445 /// @param ci Caller information.
446 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
447 void ResetAndWait( const Ticks::Duration::TDuration& maxWaitTimeSpan, const CallerInfo& ci ) {
448 Acquire(ci);
449 notified= false;
450 WaitForNotification(maxWaitTimeSpan, ci);
451 Release(ci);
452 }
453 #else
454 void Wait( const Ticks::Duration::TDuration& maxWaitTimeSpan )
455 {ALIB_LOCK
456 WaitForNotification(maxWaitTimeSpan);
457 }
458
459 void ResetAndWait( const Ticks::Duration::TDuration& maxWaitTimeSpan )
460 {ALIB_LOCK
461 notified= false;
462 WaitForNotification(maxWaitTimeSpan);
463 }
464 #endif
465
466
467 #if ALIB_DEBUG
468 /// Waits for notification but only for a given duration.
469 ///
470 /// Before invoking this method, this object has to be #"TCondition::Acquire;acquired".
471 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
472 /// released later.
473 /// @param maxWaitTimeSpan The maximum time to wait.
474 /// @param ci Caller information.
475 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
476 void Wait( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
477 { Wait( maxWaitTimeSpan.Export(), ci ); }
478
479 /// Clears the condition first and then waits for up to a given duration.
480 /// @param maxWaitTimeSpan The maximum time to wait.
481 /// @param ci Caller information.
482 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
483 void ResetAndWait( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
484 { ResetAndWait( maxWaitTimeSpan.Export(), ci ); }
485 #else
486 void Wait( const Ticks::Duration& maxWaitTimeSpan )
487 { Wait( maxWaitTimeSpan.Export() ); }
488
489 void ResetAndWait( const Ticks::Duration& maxWaitTimeSpan )
490 { ResetAndWait( maxWaitTimeSpan.Export() ); }
491 #endif
492
493 #if ALIB_DEBUG
494 /// Waits for notification, but only until a given point in time.
495 ///
496 /// Before invoking this method, this object has to be #"TCondition::Acquire;acquired".
497 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
498 /// released later.
499 ///
500 /// @param wakeUpTime The point in time to wake up, even if not notified.
501 /// @param ci Caller information.
502 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
503 /// Waits until the condition is set, but only until a given point in time.
504 /// This method does not modify the condition state.
505 void Wait( const Ticks& wakeUpTime, const CallerInfo& ci ) {
506 Acquire(ci);
507 WaitForNotification(wakeUpTime, ci);
508 Release(ci);
509 }
510
511 /// Clears the condition first and then waits until a given point in time.
512 /// @param wakeUpTime The point in time to wake up, even if not notified.
513 /// @param ci Caller information.
514 /// Use the macro #"ALIB_COMMA_CALLER_PRUNED" with invocations.
515 void ResetAndWait( const Ticks& wakeUpTime, const CallerInfo& ci ) {
516 Acquire(ci);
517 notified= false;
518 WaitForNotification(wakeUpTime, ci);
519 Release(ci);
520 }
521 #else
522 void Wait( const Ticks& wakeUpTime )
523 {ALIB_LOCK
524 WaitForNotification(wakeUpTime);
525 }
526
527 void ResetAndWait( const Ticks& wakeUpTime )
528 {ALIB_LOCK
529 notified= false;
530 WaitForNotification(wakeUpTime);
531 }
532 #endif
533};
534
535} // namespace alib[threads]
536
537/// Type alias in namespace \b alib.
538template<typename T= bool>
540
541/// Type alias in namespace \b alib.
543
544} // namespace [alib]
545
546
547#endif // !ALIB_SINGLE_THREADED
#define ALIB_DBG_TAKE_CI
Definition alib.inl:1108
#define ALIB_CALLER
Definition alib.inl:1096
#define ALIB_EXPORT
Definition alib.inl:562
#define ALIB_LOCK
Definition alib.inl:1410
#define ALIB_DBG(...)
Definition alib.inl:931
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.inl:298
static Thread * Get(std::thread::id nativeID)
Definition thread.cpp:314
TTimePoint Export() const
constexpr bool IsNull(const T &t)
Definition tmp.inl:48
constexpr bool IsNotNull(const T &t)
Definition tmp.inl:55
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.inl:79
characters::character character
Type alias in namespace alib.
std::thread::id ThreadID
The ID of the calling thread.
DbgConditionAsserter Dbg
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.inl:91
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)