ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
locks.cpp
1#if !ALIB_SINGLE_THREADED
2
3namespace alib { namespace threads {
4
5//##################################################################################################
6// Globals
7//##################################################################################################
8/// This global mutex is acquired by \alib-types, whenever data is written to either
9/// <c>std::cout</c> or <c>std::cerr</c>.
10/// This is, for example, acquired by function #"alib::assert::Raise;3" and by loggers of
11/// module \alib_alox that log to the console
12/// (#"alib_mod_alox_loggers_textlogger_stdio_lock;see here").
13///
14/// The utility type #"std::OStreamWriter" uses this lock as well
15/// as C++20 type <b>std::basic_osyncstream</b> (if available with the toolchain used) to have
16/// maximum protection in respect to writing to the console.
18
19//##################################################################################################
20// Debug-Versions of Lock-Types
21//##################################################################################################
22#if ALIB_DEBUG
24 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
25
26 if ( !Dbg.WaitTimeLimit.IsZero() ) {
27 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
28 Ticks overallTimer;
29 Ticks waitTimer;
30 while (!mutex.try_lock_for( (waitDuration - waitTimer.Age()).Export() ) ) {
31 if ( waitTimer.Age() < waitDuration )
32 continue; // spurious wakeup
33
34 #if ALIB_STRINGS
35 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
36 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
37 #else
38 std::string msg("Waiting to acquire a lock since ");
39 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
40 msg+= " ms";
41 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
42 #endif
43
44 waitTimer.Reset();
45 } }
46 else
47 mutex.lock();
48
49 Dbg.SetOwner( ALIB_CALLER, ci );
50}
51
53 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
54
55 if (!mutex.try_lock() )
56 return false;
57
58 Dbg.SetOwner( ALIB_CALLER, ci );
59 return true;
60}
61
63 Dbg.AssertOwned ( ALIB_CALLER, ci );
64 Dbg.Release( ALIB_CALLER, ci);
65 mutex.unlock();
66}
67#endif // ALIB_DEBUG
68
69//##################################################################################################
70// Class TimedLock
71//##################################################################################################
72#if !ALIB_DEBUG
73bool TimedLock::TryAcquireTimed( const Ticks::Duration& waitDuration )
74{
75 Ticks::Duration remainingDuration= waitDuration;
76 Ticks timer;
77 while (!mutex.try_lock_for( remainingDuration.Export() ) )
78 {
79 remainingDuration= waitDuration - timer.Age();
80 if ( remainingDuration.IsPositive() )
81 continue; // spurious wakeup
82 return false;
83 }
84 return true;
85}
86#else
87
89 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
90
91 if ( !Dbg.WaitTimeLimit.IsZero() ) {
92 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
93 Ticks overallTimer;
94 Ticks waitTimer;
95 while (!mutex.try_lock_for( (waitDuration - waitTimer.Age()).Export() ) ) {
96 if ( waitTimer.Age() < waitDuration )
97 continue; // spurious wakeup
98
99 #if ALIB_STRINGS
100 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
101 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
102 #else
103 std::string msg("Waiting to acquire a lock since ");
104 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
105 msg+= " ms";
106 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
107 #endif
108
109 waitTimer.Reset();
110 } }
111 else
112 mutex.lock();
113
114 Dbg.SetOwner( ALIB_CALLER, ci );
115}
116
118 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
119
120 if (!mutex.try_lock() )
121 return false;
122
123 Dbg.SetOwner( ALIB_CALLER, ci );
124 return true;
125}
126
127bool TimedLock::TryAcquireTimed( const Ticks::Duration& waitDuration,
128 const CallerInfo& ci ) {
129 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
130
131 Ticks::Duration remainingDuration= waitDuration;
132 Ticks timer;
133 while (!mutex.try_lock_for( remainingDuration.Export() ) ) {
134 remainingDuration= waitDuration - timer.Age();
135 if ( remainingDuration.IsPositive() )
136 continue; // spurious wakeup
137 return false;
138 }
139
140 Dbg.SetOwner( ALIB_CALLER, ci );
141 return true;
142}
144 Dbg.AssertOwned ( ALIB_CALLER, ci );
145 Dbg.Release( ALIB_CALLER, ci);
146 mutex.unlock();
147}
148#endif // ALIB_DEBUG
149
150#if ALIB_DEBUG
152 if ( !Dbg.WaitTimeLimit.IsZero() ) {
153 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
154 Ticks overallTimer;
155 Ticks waitTimer;
156 while (!mutex.try_lock_for( (waitDuration - waitTimer.Age()).Export() ) ) {
157 if ( waitTimer.Age() < waitDuration )
158 continue; // spurious wakeup
159
160 #if ALIB_STRINGS
161 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
162 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
163 #else
164 std::string msg("Waiting to acquire a lock since ");
165 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
166 msg+= " ms";
167 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
168 #endif
169 waitTimer.Reset();
170 } }
171 else
172 mutex.lock();
173
174 Dbg.SetRecursiveOwner( ALIB_CALLER, ci );
175}
176
178 if (!mutex.try_lock() )
179 return false;
180 Dbg.SetRecursiveOwner( ALIB_CALLER, ci );
181 return true;
182}
183
185 Dbg.AssertOwned ( ALIB_CALLER, ci );
186 Dbg.Release( ALIB_CALLER, ci);
187 mutex.unlock();
188}
189#endif // ALIB_DEBUG
190
191#if !ALIB_DEBUG
192bool RecursiveTimedLock::TryAcquireTimed( const Ticks::Duration& waitDuration )
193{
194 Ticks::Duration remainingDuration= waitDuration;
195 Ticks timer;
196 while (!mutex.try_lock_for( remainingDuration.Export() ) )
197 {
198 remainingDuration= waitDuration - timer.Age();
199 if ( remainingDuration.IsPositive() )
200 continue; // spurious wakeup
201 return false;
202 }
203 return true;
204}
205#else
207 if ( !Dbg.WaitTimeLimit.IsZero() ) {
208 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
209 Ticks overallTimer;
210 Ticks waitTimer;
211 while (!mutex.try_lock_for( (waitDuration - waitTimer.Age()).Export() ) ) {
212 if ( waitTimer.Age() < waitDuration )
213 continue; // spurious wakeup
214
215 #if ALIB_STRINGS
216 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
217 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
218 #else
219 std::string msg("Waiting to acquire a lock since ");
220 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
221 msg+= " ms";
222 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
223 #endif
224
225 waitTimer.Reset();
226 } }
227 else
228 mutex.lock();
229
230 Dbg.SetRecursiveOwner( ALIB_CALLER, ci );
231}
232
234 if (!mutex.try_lock() )
235 return false;
236
237 Dbg.SetRecursiveOwner( ALIB_CALLER, ci );
238 return true;
239}
240
241bool RecursiveTimedLock::TryAcquireTimed( const Ticks::Duration& waitDuration,
242 const CallerInfo& ci ) {
243 Ticks::Duration remainingDuration= waitDuration;
244 Ticks timer;
245 while (!mutex.try_lock_for( remainingDuration.Export() ) ) {
246 remainingDuration= waitDuration - timer.Age();
247 if ( remainingDuration.IsPositive() )
248 continue; // spurious wakeup
249 return false;
250 }
251
252 Dbg.SetRecursiveOwner( ALIB_CALLER, ci );
253 return true;
254}
255
257 Dbg.AssertOwned ( ALIB_CALLER, ci );
258 Dbg.Release( ALIB_CALLER, ci);
259 mutex.unlock();
260}
261#endif // ALIB_DEBUG
262
263#if ALIB_DEBUG
265 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
266
267 if ( !Dbg.WaitTimeLimit.IsZero() ) {
268 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
269 Ticks overallTimer;
270 Ticks waitTimer;
271 while (!mutex.try_lock_for( (waitDuration - waitTimer.Age()).Export() ) ) {
272 if ( waitTimer.Age() < waitDuration )
273 continue; // spurious wakeup
274
275 #if ALIB_STRINGS
276 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
277 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
278 #else
279 std::string msg("Waiting to acquire a lock since ");
280 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
281 msg+= " ms";
282 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
283 #endif
284
285 waitTimer.Reset();
286 } }
287 else
288 mutex.lock();
289
290 Dbg.SetOwner( ALIB_CALLER, ci );
291}
292
294 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
295
296 if (!mutex.try_lock() )
297 return false;
298
299 Dbg.SetOwner( ALIB_CALLER, ci );
300 return true;
301}
302
304 Dbg.AssertOwned ( ALIB_CALLER, ci );
305 Dbg.Release( ALIB_CALLER, ci);
306 mutex.unlock();
307}
308
310 Dbg.AssertNotOwning( ALIB_CALLER, ci,
311 "AcquireShared while already owning. (This is not allowed with std::shared_lock)" );
312
313 if ( !Dbg.WaitTimeLimit.IsZero() ) {
314 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
315 Ticks overallTimer;
316 Ticks waitTimer;
317 while (!mutex.try_lock_shared_for( (waitDuration - waitTimer.Age()).Export() ) ) {
318 if ( waitTimer.Age() < waitDuration )
319 continue; // spurious wakeup
320
321 #if ALIB_STRINGS
322 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
323 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
324 #else
325 std::string msg("Waiting to acquire a lock since ");
326 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
327 msg+= " ms";
328 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
329 #endif
330
331 waitTimer.Reset();
332 } }
333 else
334 mutex.lock_shared();
335
336 Dbg.SetSharedOwner( ALIB_CALLER, ci, DbgWarningMaximumShared );
337}
338
340 Dbg.AssertNotOwning( ALIB_CALLER, ci,
341 "AcquireShared while already owning. (This is not allowed with std::shared_lock)" );
342
343 if ( !mutex.try_lock_shared() )
344 return false;
345
346 Dbg.SetSharedOwner( ALIB_CALLER, ci, DbgWarningMaximumShared );
347 return true;
348}
349
351{
352 Dbg.ReleaseShared( ALIB_CALLER, ci);
353 mutex.unlock_shared();
354}
355#endif // ALIB_DEBUG
356
357#if !ALIB_DEBUG
358bool SharedTimedLock::TryAcquireTimed( const Ticks::Duration& waitDuration )
359{
360 Ticks::Duration remainingDuration= waitDuration;
361 Ticks timer;
362 while (!mutex.try_lock_for( remainingDuration.Export() ) )
363 {
364 remainingDuration= waitDuration - timer.Age();
365 if ( remainingDuration.IsPositive() )
366 continue; // spurious wakeup
367 return false;
368 }
369 return true;
370}
371#else
373 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
374
375 if ( !Dbg.WaitTimeLimit.IsZero() ) {
376 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
377 Ticks overallTimer;
378 Ticks waitTimer;
379 while (!mutex.try_lock_for( (waitDuration - waitTimer.Age()).Export() ) ) {
380 if ( waitTimer.Age() < waitDuration )
381 continue; // spurious wakeup
382
383 #if ALIB_STRINGS
384 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
385 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
386 #else
387 std::string msg("Waiting to acquire a lock since ");
388 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
389 msg+= " ms";
390 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
391 #endif
392
393 waitTimer.Reset();
394 } }
395 else
396 mutex.lock();
397
398 Dbg.SetOwner( ALIB_CALLER, ci );
399}
401 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
402
403 if (!mutex.try_lock() )
404 return false;
405
406 Dbg.SetOwner( ALIB_CALLER, ci );
407 return true;
408}
409
410bool SharedTimedLock::TryAcquireTimed( const Ticks::Duration& waitDuration,
411 const CallerInfo& ci ) {
412 Dbg.AssertNotOwning( ALIB_CALLER, ci, "Illegal nested acquisition" );
413
414 Ticks::Duration remainingDuration= waitDuration;
415 Ticks timer;
416 while (!mutex.try_lock_for( remainingDuration.Export() ) ) {
417 remainingDuration= waitDuration - timer.Age();
418 if ( remainingDuration.IsPositive() )
419 continue; // spurious wakeup
420 return false;
421 }
422
423 Dbg.SetOwner( ALIB_CALLER, ci );
424 return true;
425}
426
428 Dbg.AssertOwned ( ALIB_CALLER, ci );
429 Dbg.Release( ALIB_CALLER, ci);
430 mutex.unlock();
431}
432#endif
433
434#if !ALIB_DEBUG
435bool SharedTimedLock::TryAcquireSharedTimed( const Ticks::Duration& waitDuration )
436{
437 Ticks::Duration remainingDuration= waitDuration;
438 Ticks timer;
439 while (!mutex.try_lock_shared_for( remainingDuration.Export() ) )
440 {
441 remainingDuration= waitDuration - timer.Age();
442 if ( remainingDuration.IsPositive() )
443 continue; // spurious wakeup
444 return false;
445 }
446 return true;
447}
448
449#else
450
452 Dbg.AssertNotOwning( ALIB_CALLER, ci,
453 "AcquireShared while already owning. (This is not allowed with std::shared_lock)" );
454
455 if ( !Dbg.WaitTimeLimit.IsZero() ) {
456 Ticks::Duration waitDuration= Dbg.WaitTimeLimit;
457 Ticks overallTimer;
458 Ticks waitTimer;
459 while (!mutex.try_lock_shared_for( (waitDuration - waitTimer.Age()).Export() ) ) {
460 if ( waitTimer.Age() < waitDuration )
461 continue; // spurious wakeup
462
463 #if ALIB_STRINGS
464 NAString msg("Waiting to acquire a lock since "); msg << overallTimer.Age();
465 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg);
466 #else
467 std::string msg("Waiting to acquire a lock since ");
468 msg+= std::format("{}", overallTimer.Age().InAbsoluteMilliseconds());
469 msg+= " ms";
470 Dbg.DoAssert( 1, ALIB_CALLER, ci, msg.c_str());
471 #endif
472
473 waitTimer.Reset();
474 } }
475 else
476 mutex.lock_shared();
477
478 Dbg.SetSharedOwner( ALIB_CALLER, ci, DbgWarningMaximumShared );
479}
480
482 Dbg.AssertNotOwning( ALIB_CALLER, ci,
483 "AcquireShared while already owning. (This is not allowed with std::shared_lock)" );
484
485 if ( !mutex.try_lock_shared() )
486 return false;
487
488 Dbg.SetSharedOwner( ALIB_CALLER, ci, DbgWarningMaximumShared );
489 return true;
490}
491
492bool SharedTimedLock::TryAcquireSharedTimed( const Ticks::Duration& waitDuration,
493 const CallerInfo& ci ) {
494 Dbg.AssertNotOwning( ALIB_CALLER, ci,
495 "AcquireShared while already owning. (This is not allowed with std::shared_lock)" );
496
497 Ticks::Duration remainingDuration= waitDuration;
498 Ticks timer;
499 while (!mutex.try_lock_shared_for( remainingDuration.Export() ) ) {
500 remainingDuration= waitDuration - timer.Age();
501 if ( remainingDuration.IsPositive() )
502 continue; // spurious wakeup
503 return false;
504 }
505
506 Dbg.SetSharedOwner( ALIB_CALLER, ci, DbgWarningMaximumShared );
507 return true;
508}
509
511{
512 Dbg.ReleaseShared( ALIB_CALLER, ci);
513 mutex.unlock_shared();
514}
515
516#endif // ALIB_DEBUG
517
518#if ALIB_DEBUG_CRITICAL_SECTIONS
519bool Lock ::DCSIsAcquired () const { return Dbg.IsOwnedByCurrentThread(); }
520bool Lock ::DCSIsSharedAcquired() const { return Dbg.IsOwnedByCurrentThread(); }
521bool TimedLock ::DCSIsAcquired () const { return Dbg.IsOwnedByCurrentThread(); }
522bool TimedLock ::DCSIsSharedAcquired() const { return Dbg.IsOwnedByCurrentThread(); }
523bool RecursiveLock ::DCSIsAcquired () const { return Dbg.IsOwnedByCurrentThread(); }
524bool RecursiveLock ::DCSIsSharedAcquired() const { return Dbg.IsOwnedByCurrentThread(); }
525bool RecursiveTimedLock::DCSIsAcquired () const { return Dbg.IsOwnedByCurrentThread(); }
526bool RecursiveTimedLock::DCSIsSharedAcquired() const { return Dbg.IsOwnedByCurrentThread(); }
527bool SharedLock ::DCSIsAcquired () const { return Dbg.IsOwnedByCurrentThread(); }
528bool SharedLock ::DCSIsSharedAcquired() const { return Dbg.IsSharedOwnedByAnyThread()
529 || Dbg.IsOwnedByCurrentThread(); }
530bool SharedTimedLock ::DCSIsAcquired () const { return Dbg.IsOwnedByCurrentThread(); }
531bool SharedTimedLock ::DCSIsSharedAcquired() const { return Dbg.IsSharedOwnedByAnyThread()
532 || Dbg.IsOwnedByCurrentThread(); }
533#endif // ALIB_DEBUG_CRITICAL_SECTIONS
534
535}} // namespace [alib::threads]
536
537#endif // !ALIB_SINGLE_THREADED
#define ALIB_DBG_TAKE_CI
#define ALIB_CALLER
DbgLockAsserter Dbg
The debug tool instance.
Definition lock.hpp:65
std::mutex mutex
Definition lock.hpp:58
void Release(ALIB_DBG_TAKE_CI)
Definition locks.cpp:62
bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:52
void Acquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:23
void AcquireRecursive(ALIB_DBG_TAKE_CI)
Definition locks.cpp:151
std::recursive_mutex mutex
void ReleaseRecursive(ALIB_DBG_TAKE_CI)
Definition locks.cpp:184
bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:177
DbgLockAsserter Dbg
The debug tool instance.
void ReleaseRecursive(ALIB_DBG_TAKE_CI)
Definition locks.cpp:256
DbgLockAsserter Dbg
The debug tool instance.
virtual bool DCSIsAcquired() const override
Definition locks.cpp:525
std::recursive_timed_mutex mutex
The internal object to lock on.
virtual bool DCSIsSharedAcquired() const override
Definition locks.cpp:526
bool TryAcquireTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci)
Definition locks.cpp:241
void AcquireRecursive(ALIB_DBG_TAKE_CI)
Definition locks.cpp:206
bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:233
bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:293
std::atomic< int > DbgWarningMaximumShared
void Release(ALIB_DBG_TAKE_CI)
Definition locks.cpp:303
std::shared_mutex mutex
DbgSharedLockAsserter Dbg
The debug tool instance.
void ReleaseShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:350
void AcquireShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:309
bool TryAcquireShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:339
void Acquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:264
DbgSharedLockAsserter Dbg
The debug tool instance.
std::shared_timed_mutex mutex
The internal object to lock on.
void AcquireShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:451
void Acquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:372
bool TryAcquireShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:481
std::atomic< int > DbgWarningMaximumShared
void ReleaseShared(ALIB_DBG_TAKE_CI)
Definition locks.cpp:510
bool TryAcquireTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci)
Definition locks.cpp:410
bool TryAcquireSharedTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci)
Definition locks.cpp:492
void Release(ALIB_DBG_TAKE_CI)
Definition locks.cpp:427
bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:400
DbgLockAsserter Dbg
The debug tool instance.
Definition timedlock.hpp:55
bool TryAcquireTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci)
Definition locks.cpp:127
void Release(ALIB_DBG_TAKE_CI)
Definition locks.cpp:143
std::timed_mutex mutex
The internal object to lock on.
Definition timedlock.hpp:50
bool TryAcquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:117
void Acquire(ALIB_DBG_TAKE_CI)
Definition locks.cpp:88
Lock STD_IOSTREAMS_LOCK
Definition locks.cpp:17
Definition alox.cpp:14
strings::TAString< nchar, lang::HeapAllocator > NAString
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