ALib C++ Library
Library Version: 2412 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/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef HPP_ALIB_THREADS_SLEEPER
9#define HPP_ALIB_THREADS_SLEEPER 1
10#pragma once
11#if !defined(DOXYGEN)
12# include "alib/alib.hpp"
13#endif
14ALIB_ASSERT_MODULE(THREADS)
15#include "alib/time/ticks.hpp"
16#include "alib/lang/owner.hpp"
17
18#if ALIB_DEBUG
21# include <atomic>
22#endif
23
24
25#include <mutex>
26#include <condition_variable>
27namespace alib { namespace threads {
28
29
30#if ALIB_DEBUG
31//==================================================================================================
32/// This type is used for debugging and asserting types \alib{threads;TCondition}.
33/// With debug compilations that class holds one member of this struct, which aggregates all
34/// debug information.
35//==================================================================================================
37{
38 String Name; ///< The name of this instance.
39 Thread* Owner{nullptr}; ///< Tracks the current owner.
40 CallerInfo AcqCI ; ///< Source location of the most recent acquirement.
41 CallerInfo RelCI ; ///< Source location of the most recent release.
42 CallerInfo WaitCI; ///< The most recent call to \b WaitForNotification.
43 CallerInfo NotifyCI; ///< The most recent call to \b ReleaseAndNotify or
44 std::atomic<int> CntWaiters{0}; ///< The number of currently waiting threads.
45 std::thread::id AssertExclusiveWaiter; ///< If set from outside, methods \b WaitForNotification
46 ///< will raise an assertion in the case they are called
47 ///< from a different thread.
48#if ALIB_CAMP
49 /// The format string used to write exceptions to the console.
50 /// This string can be changed if the source information is not "clickable" in a user's
51 /// development environment.<br>
52 ///
53 /// The default string is optimized for
54 /// \https{JetBrains CLion,www.jetbrains.com/clion} and is defined as:
55 /** \verbatim
56Assertion failed in method TCondition::{2:sm}
57 Message: {0}
58 Instance: {1}
59
60 Called By: {3:ya}
61 At: {3:sf:sl}
62 Thread: {3:ta}
63
64 Current Owner: {4}
65 #Of Waiters: {5}
66 Exclusive Waiter: {6}
67
68 Latest Acquisition By: {7:ya}
69 At: {7:sf:sl}
70 Thread: {7:ta}
71 Latest Release By: {8:ya}
72 At: {8:sf:sl}
73 Thread: {8:ta}
74
75 Latest Wait By: {9:ya}
76 At: {9:sf:sl}
77 Thread: {9:ta}
78 Latest Notify By: {10:ya}
79 At: {10:sf:sl}
80 Thread: {10:ta}
81 \endverbatim
82 <p>
83 The placeholder fields that this format string refers to are set as follows:
84 - \c 0: Headline.
85 - \c 1: Debug-name of the condition.
86 - \c 2: \b %CallerInfo of assertion.
87 - \c 3: \b %CallerInfo of caller.
88 - \c 4: \b %CallerInfo of latest acquisition.
89 - \c 5: The number of waiting threads.
90 - \c 6: <c>std::thread::id</c> of an exclusive waiter thread (which can be optionally set).
91 - \c 7: \b %CallerInfo of latest acquisition.
92 - \c 8: \b %CallerInfo of latest release.
93 - \c 9: \b %CallerInfo of latest wait call.
94 - \c 10: \b %CallerInfo of latest notification.
95
96 The format specification of the type \c CallerInfo is defined with class
97 \alib{lang::format;FMTCallerInfo}.
98 \par Availability:
99 This field is only available with the inclusion of \alib_basecamp in the \alibdist.<br> */
102#endif
103
104 /// Writes assertion info and calls \ref ALIB_ASSERT.
105 /// @see
106 /// Field #ASSERTION_FORMAT which allows changing the output format to achieve 'clickable'
107 /// assertion messages.
108 /// @param cond The condition that is to be met.
109 /// @param assertCI Location where the assertion is placed.
110 /// @param ci Location of the call to the method that asserted.
111 /// @param headline The message.
113 void Assert( bool cond, const CallerInfo& assertCI, const CallerInfo& ci,
114 const NString& headline );
115
116 /// Returns \c true if the current owner is the current thread.<p>
117 /// Available only in debug-builds.
118 /// @return \c true, if the lock is owned by this thread, \c false if it is owned by
119 /// another thread or not owned.
121 { return Owner != nullptr && Owner == Thread::GetCurrent() ; }
122
123}; // struct DbgConditionAsserter
124#endif // ALIB_DEBUG
125
126
127/// This struct wraps C++ standard library types \c std::mutex and \c std::condition_variable.
128/// It allows one or more threads to sleep until any other thread satisfies a condition and
129/// wakes one or all threads up.
130///
131/// \par Abstract Template Type:
132/// This class is an <em>"abstract template type"</em>, which means that it invokes methods
133/// which are not declared and thus have to be declared by a type that derives from this class.
134/// The derived type needs to pass its own type name to template parameter \p{TDerived}.<br>
135/// With that, this type can cast its <c>this</c>-pointer to that type and access its interface.
136/// The derived type has to provide only one function member:
137///
138/// bool isConditionMet()
139/// \par
140/// This has to return \c true if the condition is fulfilled, otherwise \c false.
141///
142/// \par Acquisition Rules:
143/// Before using one of the overloaded blocking sleep methods #WaitForNotification, the object
144/// has to be locked by calling #Acquire.
145/// Such acquirement is guaranteed to be held after the method returns.
146/// \par
147/// A notifying thread has to likewise acquire this object before calling either
148/// #ReleaseAndNotify or #ReleaseAndNotifyAll.
149/// However, as the method names indicate, with the return from the notification call, the
150/// internal mutex is released.
151/// \par
152/// Similar to class \alib{threads;Lock}, nested calls to the method #Acquire are not allowed and
153/// constitute undefined behavior.
154///
155/// \par Usage Recipe:
156/// Being an <em>"abstract"</em> type, the class is not designed for direct use.
157/// Instead, a derived type should expose its own, dedicated interface, which replaces
158/// this type's interface.
159/// As a sample, let us look at provided derived type \alib{threads;Condition}, which implements
160/// the simplest possible use-case of this class:
161/// - The type has protected inheritance to this struct.
162/// - Protected method \alib{threads::Condition;isConditionMet} is defined, which returns \c true if
163/// the instance was notified.
164/// - This parent struct is made a friend too enable access to the protected method.
165/// - Own interface methods are provided. In this case methods
166/// \alib{threads::Condition;Notify}, \alib{threads::Condition;NotifyAll}, and
167/// \alib{threads::Condition;Wait}.
168/// \par
169/// A more sophisticated but still simple implementation can be reviewed by analyzing the
170/// source of type job-queues in classes \alib{threadmodel;DedicatedWorker} and
171/// \alib{threadmodel;ThreadPool}.
172/// Its corresponding interface methods are <em>push</em> and <em>pop</em> alike,
173/// which do not resemble too much to the terms wait/notify anymore.
174///
175/// \par Debug-Information:
176/// With debug-builds, several assertions are made to avoid wrong use of the type.
177/// This is implemented by adding the field member #Dbg.
178/// The output format of assertions should be 'clickable' inside a users' IDE.
179/// The default output string is optimized for
180/// \https{JetBrains CLion,www.jetbrains.com/clion} and can be changed by manipulating
181/// the static field member \alib{threads;DbgConditionAsserter::ASSERTION_FORMAT}.
182///
183/// @see
184/// - Chapter \ref alib_manual_appendix_callerinfo of the General Programmer's Manual.
185/// - For this class, a \ref alibtools_debug_helpers_gdb "pretty printer" for the
186/// GNU debugger is provided.
187///
188/// @tparam TDerived The derived type which provides method \b isConditionMet.
189template<typename TDerived>
191{
192 /// The mutex used for locking this instance.
193 std::mutex mutex;
194
195 /// The condition variable used for blocking and notification.
196 std::condition_variable conditionVariable;
197
198 /// Helper to statically casts this object to the derived type.
199 /// @return <c>*this</c> cast to a reference of \p{TDerived}.
200 TDerived& cast() { return static_cast<TDerived&>(*this); }
201
202
203 #if ALIB_DEBUG
204 /// The debug tool instance.
206
207 /// Constructor.
208 /// @param dbgName The name of this instance.<br>
209 /// Available only with debug-builds.
210 /// With release-builds, this type is default
211 /// constructed. Hence, this parameter has to be provided using macro
212 /// \ref ALIB_DBG, which prunes the name away.
213 TCondition(const String& dbgName) { Dbg.Name= dbgName; }
214 #else
215 TCondition() = default;
216 #endif
217
218 //==============================================================================================
219 /// A thread which invokes this method gets registered as the current owner of this object,
220 /// until the same thread releases the ownership invoking #Release.
221 /// In the case that this object is already owned by another thread, the invoking thread is
222 /// suspended until ownership can be gained.<p>
223 /// Multiple (nested) calls to this method are <b>not supported</b> and constitute
224 /// undefined behavior. In debug-compilations, an assertion is raised.
225 ///
226 /// An instance has to be acquired before invoking any of the notifiy- or wait-methods.
227 /// When return from a notification method, the instance is released.
228 /// With return from a wait method, the instance is still held.
229 ///
230 /// \par Debug Parameter:
231 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
232 //==============================================================================================
234 {
235 #if ALIB_DEBUG
237 "Acquire: Multiple acquirements of TCondition are forbidden." );
238 #endif
239
240 mutex.lock();
241
242 #if ALIB_DEBUG
243 Dbg.Assert( Dbg.Owner==nullptr, ALIB_CALLER, ci,
244 "Acquire: Owner is (still) set, after std::mutex.lock()." );
245 Dbg.AcqCI = ci;
246 Dbg.Owner = Thread::Get(ci.ThreadID);
247 #endif
248 }
249
250 //==============================================================================================
251 /// Releases ownership of this object.
252 /// If this method is invoked on an object that is not acquired or acquired by a different
253 /// thread, in debug-compilations an assertion is raised.
254 /// In release compilations, this leads to undefined behavior.
255 /// @see Method #Acquire.
256 /// \par Debug Parameter:
257 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
258 //==============================================================================================
260 {
261 #if ALIB_DEBUG
262 Dbg.Assert( lang::IsNotNull(Dbg.Owner), ALIB_CALLER, ci, "Release: Not acquired." );
264 "Release: Ownership is with a different thread" );
265 Dbg.RelCI = ci;
266 Dbg.Owner= nullptr;
267 #endif
268
269 mutex.unlock();
270 }
271
272 //==============================================================================================
273 /// Unblock a next waiting thread.<p>
274 /// As the method name indicates, with this implementation, it is necessary to acquire this
275 /// object before invoking this method.
276 /// Internally, the mutex will be released, and thus no separate call to #Release is necessary,
277 /// respectively allowed.
278 ///
279 /// \par Debug Parameter:
280 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
281 //==============================================================================================
283 {
284 #if ALIB_DEBUG
286 "ReleaseAndNotify called without prior acquisition" );
287
289 "ReleaseAndNotify: Ownership is with a different thread" );
290
291 Dbg.Owner= nullptr;
292 Dbg.NotifyCI= ci;
293 Dbg.Owner= nullptr;
294 #endif
295
296 mutex.unlock();
297 conditionVariable.notify_one();
298 }
299
300 //==============================================================================================
301 /// Releases the internal mutex and wakes up all sleeping threads.
302 /// \par Debug Parameter:
303 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
304 //==============================================================================================
306 {
307 #if ALIB_DEBUG
309 "An exclusive waiter is set. Thus, notifying 'all' is not allowed.");
310
312 "ReleaseAndNotify called without prior acquisition" );
313
315 "ReleaseAndNotify: Ownership is with a different thread" );
316
317 Dbg.Owner= nullptr;
318 Dbg.NotifyCI= ci;
319 #endif
320
321 mutex.unlock();
322 conditionVariable.notify_all();
323 }
324
325 //==============================================================================================
326 /// Waits for notification (for an unlimited time).<br>
327 /// Before invoking this method, this object has to be \ref Acquire "acquired".
328 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
329 /// released by the owner.<br>
330 /// It is allowed to create (endless) loops that never actively release this instance
331 /// but call one of the waiting methods instead.<br>
332 /// Note that "spurious wake-ups" are internally caught with this implementation.
333 /// \par Debug Parameter:
334 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
335 //==============================================================================================
337 {
338 #if ALIB_DEBUG
340 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
341 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
342
344 "WaitForNotification called without prior acquisition" );
345
347 "WaitForNotification: Ownership is with a different thread" );
348
349 ++Dbg.CntWaiters;
350 Dbg.WaitCI= ci;
351 Dbg.Owner= nullptr;
352 #endif
353
354 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
355 conditionVariable.wait( lock, [this]{ return cast().isConditionMet(); } );
356 lock.release();
357
358 #if ALIB_DEBUG
359 Dbg.Owner= Thread::Get(ci.ThreadID);
360 --Dbg.CntWaiters;
361 #endif
362 }
363
364 #if !ALIB_DEBUG
365 void WaitForNotification( const Ticks::Duration::TDuration& maxWaitTimeSpan)
366 {
367 #else
368 //==============================================================================================
369 /// Same as #WaitForNotification(ALIB_DBG_TAKE_CI), but takes a C++ time span that defines
370 /// a maximum wait time.
371 ///
372 /// @param maxWaitTimeSpan The maximum time to wait.
373 /// @param ci Caller information.
374 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
375 //==============================================================================================
376 void WaitForNotification( const Ticks::Duration::TDuration& maxWaitTimeSpan, const CallerInfo& ci )
377 {
379 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
380 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
381
383 "WaitForNotification called without prior acquisition" );
384
386 "WaitForNotification: Ownership is with a different thread" );
387
388 ++Dbg.CntWaiters;
389 Dbg.WaitCI= ci;
390 Dbg.Owner= nullptr;
391 #endif
392
393 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
394 conditionVariable.wait_for( lock, maxWaitTimeSpan, [this]{ return cast().isConditionMet(); } );
395 lock.release();
396
397 #if ALIB_DEBUG
399 --Dbg.CntWaiters;
400 #endif
401 }
402
403 #if ALIB_DEBUG
404 //==============================================================================================
405 /// Same as #WaitForNotification(ALIB_DBG_TAKE_CI), but takes a time span that defines
406 /// a maximum wait time.
407 ///
408 /// @param maxWaitTimeSpan The maximum time to wait.
409 /// @param ci Caller information.
410 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
411 //==============================================================================================
412 void WaitForNotification( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
413 { WaitForNotification( maxWaitTimeSpan.Export(), ci ); }
414 #else
415 void WaitForNotification( const Ticks::Duration& maxWaitTimeSpan )
416 { WaitForNotification( maxWaitTimeSpan.Export() ); }
417 #endif
418
419
420 #if !ALIB_DEBUG
421 void WaitForNotification( const Ticks& wakeUpTime )
422 {
423 #else
424 //==============================================================================================
425 /// Same as #WaitForNotification(ALIB_DBG_TAKE_CI), but takes a point in time at which
426 /// waiting stops.
427 ///
428 /// @param wakeUpTime The point in time to wake up, even if not notified.
429 /// @param ci Caller information.
430 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
431 //==============================================================================================
432 void WaitForNotification( const Ticks& wakeUpTime, const CallerInfo& ci )
433 {
435 || Dbg.AssertExclusiveWaiter == std::this_thread::get_id(), ALIB_CALLER, ci,
436 "WaitForNotification called by a different thread than granted with 'Dbg.AssertExclusiveWaiter'.");
437
439 "WaitForNotification called without prior acquisition" );
440
442 "WaitForNotification: Ownership is with a different thread" );
443
444
445 ++Dbg.CntWaiters;
446 Dbg.WaitCI= ci;
447 Dbg.Owner= nullptr;
448 #endif
449
450 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
451 conditionVariable.wait_until( lock, wakeUpTime.Export(),
452 [this]{ return cast().isConditionMet(); } );
453 lock.release();
454
455 #if ALIB_DEBUG
457 --Dbg.CntWaiters;
458 #endif
459 }
460};
461
462/// Extends <em>"abstract template type"</em> \alib{threads;TCondition}.
463/// This implementation constitutes the simplest possible derivate, by
464/// 1. holding just a boolean member, and
465/// 2. by providing a similar generic interface.
466/// @see
467/// Chapter \ref alib_manual_appendix_callerinfo of the General Programmer's Manual.
468class Condition : protected TCondition<Condition>
469{
470 /// the parent type needs to be able to call protected method #isConditionMet.
471 friend struct TCondition<Condition>;
472
473 protected:
474 /// Boolean member which records notifications. Defaults to not-notified.
475 bool notified = false;
476
477 /// In general, derivates of \alib{threads;TCondition} have to return \c true if the former
478 /// reason for blocking a thread is now fulfilled.
479 ///
480 /// @return This implementation returns the value of field member #notified.
481 bool isConditionMet() { return notified; }
482
483 public:
484 using TCondition<Condition>::Acquire;
485 using TCondition<Condition>::Release;
486
487 //################################################################################################
488 //### Debug implementation
489 //################################################################################################
490 #if ALIB_DEBUG
491 /// Defaulted default constructor.
492 /// @param dbgName A name for the condition. Only available with debug-compilations.
493 Condition(const character* dbgName) : TCondition(dbgName) {}
494 #else
495 Condition() = default;
496 #endif
497
498 /// Wakes up the next sleeping thread.
499 /// \par Debug Parameter:
500 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
502 {
503 Acquire(ALIB_DBG(ci));
504 notified= true;
505 ReleaseAndNotify(ALIB_DBG(ci));
506 }
507
508 /// Wakes up all sleeping threads.
509 /// \par Debug Parameter:
510 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
512 {
513 Acquire(ALIB_DBG(ci));
514 notified= true;
515 ReleaseAndNotifyAll(ALIB_DBG(ci));
516 }
517
518 /// Waits for notification (for an unlimited time).<p>
519 /// \par Debug Parameter:
520 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
522 {
523 #if ALIB_DEBUG
524 Acquire(ci);
525 notified= false;
526 WaitForNotification(ci);
527 Release(ci);
528 #else
530 notified= false;
531 WaitForNotification();
532 #endif
533 }
534
535 #if ALIB_DEBUG
536 //==============================================================================================
537 /// Same as #Wait(const Ticks::Duration&, const CallerInfo&), but takes a
538 /// C++ time span.
539 ///
540 /// @param maxWaitTimeSpan The maximum time to wait.
541 /// @param ci Caller information.
542 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
543 //==============================================================================================
544 void Wait( const Ticks::Duration::TDuration& maxWaitTimeSpan, const CallerInfo& ci )
545 {
546 Acquire(ci);
547 notified= false;
548 WaitForNotification(maxWaitTimeSpan, ci);
549 Release(ci);
550 }
551 #else
552 void Wait( const Ticks::Duration::TDuration& maxWaitTimeSpan )
553 {ALIB_LOCK
554 notified= false;
555 WaitForNotification(maxWaitTimeSpan);
556 }
557 #endif
558
559
560 #if ALIB_DEBUG
561 //==============================================================================================
562 /// Waits for notification but only for a given duration.
563 ///
564 /// Before invoking this method, this object has to be \ref Acquire "acquired".
565 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
566 /// released later.
567 ///
568 /// @param maxWaitTimeSpan The maximum time to wait.
569 /// @param ci Caller information.
570 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
571 //==============================================================================================
572 void Wait( const Ticks::Duration& maxWaitTimeSpan, const CallerInfo& ci )
573 { Wait( maxWaitTimeSpan.Export(), ci ); }
574 #else
575 void Wait( const Ticks::Duration& maxWaitTimeSpan )
576 { Wait( maxWaitTimeSpan.Export() ); }
577 #endif
578
579 #if ALIB_DEBUG
580 //==============================================================================================
581 /// Waits for notification, but only until a given point in time.
582 ///
583 /// Before invoking this method, this object has to be \ref Acquire "acquired".
584 /// After the wake-up call, the internal mutex is (again) acquired and thus has to be
585 /// released later.
586 ///
587 /// @param wakeUpTime The point in time to wake up, even if not notified.
588 /// @param ci Caller information.
589 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
590 //==============================================================================================
591 void Wait( const Ticks& wakeUpTime, const CallerInfo& ci )
592 {
593 Acquire(ci);
594 notified= false;
595 WaitForNotification(wakeUpTime, ci);
596 Release(ci);
597 }
598 #else
599 void Wait( const Ticks& wakeUpTime )
600 {ALIB_LOCK
601 notified= false;
602 WaitForNotification(wakeUpTime);
603 }
604 #endif
605};
606
607} // namespace alib[::threads]
608
609/// Type alias in namespace \b alib.
610template<typename T= bool>
612
613/// Type alias in namespace \b alib.
615
616} // namespace [alib]
617
618#endif // HPP_ALIB_THREADS_SLEEPER
619
Condition(const character *dbgName)
void Notify(ALIB_DBG_TAKE_CI)
void Wait(const Ticks::Duration::TDuration &maxWaitTimeSpan, const CallerInfo &ci)
void Wait(const Ticks &wakeUpTime, const CallerInfo &ci)
void Wait(ALIB_DBG_TAKE_CI)
void Wait(const Ticks::Duration &maxWaitTimeSpan, const CallerInfo &ci)
void NotifyAll(ALIB_DBG_TAKE_CI)
static Thread * GetCurrent()
Definition thread.hpp:283
static ALIB_API Thread * Get(std::thread::id nativeID)
Definition thread.cpp:321
TTimePoint Export() const
#define ALIB_DBG_TAKE_CI
Definition alib.hpp:1176
#define ALIB_ASSERT_MODULE(modulename)
Definition alib.hpp:223
#define ALIB_CALLER
Definition alib.hpp:1164
#define ALIB_API
Definition alib.hpp:639
#define ALIB_LOCK
Definition owner.hpp:453
#define ALIB_DBG(...)
Definition alib.hpp:390
constexpr bool IsNotNull(const T &t)
Definition alib.hpp:1054
constexpr bool IsNull(const T &t)
Definition alib.cpp:69
threads::TCondition< T > TCondition
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
std::thread::id ThreadID
The ID of the calling thread.
Definition alib.hpp:1136
CallerInfo WaitCI
The most recent call to WaitForNotification.
Definition condition.hpp:42
CallerInfo AcqCI
Source location of the most recent acquirement.
Definition condition.hpp:40
CallerInfo RelCI
Source location of the most recent release.
Definition condition.hpp:41
CallerInfo NotifyCI
The most recent call to ReleaseAndNotify or.
Definition condition.hpp:43
ALIB_API void Assert(bool cond, const CallerInfo &assertCI, const CallerInfo &ci, const NString &headline)
Definition locks.cpp:223
String Name
The name of this instance.
Definition condition.hpp:38
static ALIB_API NString ASSERTION_FORMAT
std::atomic< int > CntWaiters
The number of currently waiting threads.
Definition condition.hpp:44
Thread * Owner
Tracks the current owner.
Definition condition.hpp:39
void ReleaseAndNotifyAll(ALIB_DBG_TAKE_CI)
std::mutex mutex
The mutex used for locking this instance.
void WaitForNotification(ALIB_DBG_TAKE_CI)
void WaitForNotification(const Ticks::Duration &maxWaitTimeSpan, const CallerInfo &ci)
DbgConditionAsserter Dbg
The debug tool instance.
void WaitForNotification(const Ticks::Duration::TDuration &maxWaitTimeSpan, const CallerInfo &ci)
void Acquire(ALIB_DBG_TAKE_CI)
void Release(ALIB_DBG_TAKE_CI)
TCondition(const String &dbgName)
std::condition_variable conditionVariable
The condition variable used for blocking and notification.
void ReleaseAndNotify(ALIB_DBG_TAKE_CI)