ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
timedlock.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 \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#if !ALIB_SINGLE_THREADED
9ALIB_EXPORT namespace alib { namespace threads {
10
11// =================================================================================================
12/// This class is a simple wrapper around C++ standard library type \c std::timed_mutex.
13/// Thus, it is used to implement <em>mutual exclusive access</em> to resources by protecting
14/// critical code sections from being executed in parallel in concurrent threads.<br>
15/// With release-compilations, the only difference to using \c std::timed_mutex directly
16/// is that "spurious wake-ups" are detected and mitigated by this implementation.
17///
18/// When a pair of #Acquire and #Release invocations is performed within the same code block, then
19/// it is recommended to use a stack instantiation of class \alib{lang;Owner} to acquire and release
20/// objects of this class. Such a use is highly simplified with macros \ref ALIB_LOCK and
21/// \ref ALIB_LOCK_WITH.
22///
23/// This class does not allow nested calls to the method #Acquire - method #Release has to be
24/// invoked (from within the same thread that acquired this mutex), before any other thread can
25/// again gain access. Nested acquisitions constitute undefined behavior.
26///
27/// \par Debug-Features
28/// Public member #Dbg is available with debug-compilations. It offers the following features:
29/// - An assertion is raised when nested use is performed.
30/// - The object stores the actual owning thread and the source code position of the last
31/// acquirement.
32/// - Releasing non-acquired instances, as well as destructing acquired one, raise an assertion.
33/// - Field \alib{threads;DbgLockAsserter;WaitTimeLimit} enables the raise of \alib warnings
34/// in case a certain wait time is exceeded.
35///
36/// \par Availability
37/// This type is not available if the compiler-symbol \ref ALIB_SINGLE_THREADED is set.
38///
39/// @see
40/// - Chapter \ref alib_threads_locks of the Programmer's Manual of the module \alib_threads_nl.
41/// - Chapter \ref alib_manual_appendix_callerinfo of the General Programmer's Manual.
42// =================================================================================================
46#endif
47{
48 protected:
49 /// The internal object to lock on.
50 std::timed_mutex mutex;
51
52 public:
53 #if ALIB_DEBUG
54 /// The debug tool instance.
56 #endif
57
58 #if ALIB_DEBUG_CRITICAL_SECTIONS
59 /// Destructor. With debug-compilations, asserts that this lock is not acquired.
60 ~TimedLock() override
61 { Dbg.AssertNotOwned( ALIB_CALLER, ALIB_CALLER, "Destructing acquired lock" ); }
62
63 /// @return \c true if the lock is acquired (in non-shared mode), \c false otherwise.
64 ALIB_DLL virtual bool DCSIsAcquired() const override;
65
66 /// @return \c true if the lock is shared-acquired (by at least any thread).
67 /// Otherwise, returns \c false.
68 ALIB_DLL virtual bool DCSIsSharedAcquired() const override;
69 #elif ALIB_DEBUG
71 { Dbg.AssertNotOwned( ALIB_CALLER, ALIB_CALLER, "Destructing acquired lock" ); }
72 #endif
73
74 #if ALIB_DEBUG || DOXYGEN
75 /// Same as #TryAcquireTimed(const Ticks::Duration&, const CallerInfo&)
76 /// but misses the parameter \p{waitTime}. Using this method, the behavior is equivalent to that
77 /// of sibling type \alib{threads;Lock}.
78 ///
79 /// \par Debug Parameter:
80 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
83
84 /// Tries to acquire this lock.
85 /// Multiple (nested) successful calls to this method or method #Acquire are not supported and
86 /// lead to undefined behavior.
87 ///
88 /// \par Debug Parameter:
89 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
90 /// @return \c true if the lock was not acquired by a different thread and thus, this
91 /// call was successful. \c false otherwise.
93 [[nodiscard]]
95
96 /// A thread which invokes this method gets registered as the current owner of this object,
97 /// until the same thread releases the ownership invoking #Release.
98 /// In the case that this object is already owned by another thread, the invoking thread is
99 /// suspended until ownership can be gained.
100 /// Multiple (nested) calls to this method are not supported and lead to undefined behavior.
101 ///
102 /// @param waitDuration The maximum time-span to wait.
103 /// @param ci Caller information.
104 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
105 /// @return \c true if the lock was acquired, \c false if the \p{waitDuration} expired
106 /// without successful acquisition
108 [[nodiscard]]
109 bool TryAcquireTimed( const Ticks::Duration& waitDuration, const CallerInfo& ci );
110
111 /// Same as overloaded sibling, but expects a C++ standard library duration type
112 /// rather than an \b Ticks::Duration.
113 /// @param waitDuration The point in time, when this method stops waiting.
114 /// @param ci Caller information.
115 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
116 /// @return \c true if the lock was acquired, \c false if the \p{pointInTime} was reached
117 /// without successful acquisition.
118 [[nodiscard]]
119 bool TryAcquireTimed( const Ticks::Duration::TDuration& waitDuration, const CallerInfo& ci )
120 { return TryAcquireTimed( Ticks::Duration(waitDuration), ci); }
121
122 /// Same as overloaded sibling, but expects a point in time rather than an \b Ticks::Duration.
123 /// @param pointInTime The point in time, when this method stops waiting.
124 /// @param ci Caller information.
125 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
126 /// @return \c true if the lock was acquired, \c false if the \p{pointInTime} was reached
127 /// without successful acquisition.
128 [[nodiscard]]
129 bool TryAcquireTimed( const Ticks& pointInTime, const CallerInfo& ci )
130 { return TryAcquireTimed( pointInTime - Ticks::Now(), ci); }
131
132 /// Same as overloaded sibling, but expects a C++ standard library point in time type
133 /// rather than an \b Ticks::Duration.
134 /// @param pointInTime The point in time, when this method stops waiting.
135 /// @param ci Caller information.
136 /// Use macro \ref ALIB_COMMA_CALLER_PRUNED with invocations.
137 /// @return \c true if the lock was acquired, \c false if the \p{pointInTime} was reached
138 /// without successful acquisition.
139 [[nodiscard]]
140 bool TryAcquireTimed( const Ticks::TTimePoint& pointInTime, const CallerInfo& ci )
141 { return TryAcquireTimed( Ticks(pointInTime), ci); }
142
143 /// Releases ownership of this object.
144 /// If this method is invoked on an object that is not acquired, in debug-compilations an
145 /// assertion is raised. In release compilations, this leads to undefined behavior.
146 /// \par Debug Parameter:
147 /// Pass macro \ref ALIB_CALLER_PRUNED with invocations.
150
151 #else // release
152 void Acquire() { mutex.lock(); }
153 [[nodiscard]] bool TryAcquire() { return mutex.try_lock(); }
154 ALIB_DLL [[nodiscard]] bool TryAcquireTimed( const Ticks::Duration& waitDuration );
155 [[nodiscard]] bool TryAcquireTimed( const Ticks::Duration::TDuration& waitDuration ) { return TryAcquireTimed( Ticks::Duration(waitDuration) ); }
156 [[nodiscard]] bool TryAcquireTimed( const Ticks& pointInTime ) { return TryAcquireTimed( pointInTime - Ticks::Now() ); }
157 [[nodiscard]] bool TryAcquireTimed( const Ticks::TTimePoint& pointInTime ) { return TryAcquireTimed( Ticks(pointInTime) ); }
158 void Release() { mutex.unlock(); }
159
160 #endif
161};
162
163} // namespace alib[threads]
164
165/// Type alias in namespace \b alib.
167
168} // namespace [alib]
169#endif // !ALIB_SINGLE_THREADED
170
171
~TimedLock() override
Destructor. With debug-compilations, asserts that this lock is not acquired.
Definition timedlock.inl:60
DbgLockAsserter Dbg
The debug tool instance.
Definition timedlock.inl:55
ALIB_DLL bool TryAcquireTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci)
Definition locks.cpp:178
bool TryAcquireTimed(const Ticks::Duration::TDuration &waitDuration, const CallerInfo &ci)
ALIB_DLL void Release(ALIB_DBG_TAKE_CI)
Definition locks.cpp:199
bool TryAcquireTimed(const Ticks &pointInTime, const CallerInfo &ci)
virtual ALIB_DLL bool DCSIsSharedAcquired() const override
Definition locks.cpp:762
bool TryAcquireTimed(const Ticks::TTimePoint &pointInTime, const CallerInfo &ci)
virtual ALIB_DLL bool DCSIsAcquired() const override
Definition locks.cpp:761
std::timed_mutex mutex
The internal object to lock on.
Definition timedlock.inl:50
ALIB_DLL bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:164
ALIB_DLL void Acquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:129
typename std::chrono::steady_clock::time_point TTimePoint
#define ALIB_DBG_TAKE_CI
Definition alib.inl:1013
#define ALIB_DLL
Definition alib.inl:496
#define ALIB_CALLER
Definition alib.inl:1001
#define ALIB_EXPORT
Definition alib.inl:488
#define ALIB_DEBUG_CRITICAL_SECTIONS
Definition prepro.md:43
threads::TimedLock TimedLock
Type alias in namespace alib.
lang::CallerInfo CallerInfo
Type alias in namespace alib.
time::Ticks Ticks
Type alias in namespace alib.
Definition ticks.inl:109
void AssertNotOwned(const CallerInfo &assertCI, const CallerInfo &ci, const char *headline)