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