CppCommon 1.0.6.0
C++ Common Library
Loading...
Searching...
No Matches
named_rw_lock.cpp
Go to the documentation of this file.
1
8
10
11#include "errors/fatal.h"
12#include "system/shared_type.h"
13#include "threads/thread.h"
15
16#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
17#include <fcntl.h>
18#include <semaphore.h>
19#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
20#include <windows.h>
21#undef Yield
22#endif
23
24namespace CppCommon {
25
27
29
82class NamedRWLock::Impl
83{
84 const uint32_t LOCK_OWNED = 0x1;
85 const uint32_t LOCK_EXCLUSIVE_WAKING = 0x2;
86
87 const uint32_t LOCK_SHARED_OWNERS_SHIFT = 2;
88 const uint32_t LOCK_SHARED_OWNERS_MASK = 0x3ff;
89 const uint32_t LOCK_SHARED_OWNERS_INC = 0x4;
90
91 const uint32_t LOCK_SHARED_WAITERS_SHIFT = 12;
92 const uint32_t LOCK_SHARED_WAITERS_MASK = 0x3ff;
93 const uint32_t LOCK_SHARED_WAITERS_INC = 0x1000;
94
95 const uint32_t LOCK_EXCLUSIVE_WAITERS_SHIFT = 22;
96 const uint32_t LOCK_EXCLUSIVE_WAITERS_MASK = 0x3ff;
97 const uint32_t LOCK_EXCLUSIVE_WAITERS_INC = 0x400000;
98
99 const uint32_t LOCK_EXCLUSIVE_MASK = (LOCK_EXCLUSIVE_WAKING | (LOCK_EXCLUSIVE_WAITERS_MASK << LOCK_EXCLUSIVE_WAITERS_SHIFT));
100
101public:
102 Impl(const std::string& name, uint32_t spin) : _value(name), _spin(spin)
103 {
104 // Owner of the read/write lock should initialize its value
105 if (_value.owner())
106 *_value = 0;
107#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
108 if (_value.owner())
109 {
110 _exclusive_wake = sem_open((this->name() + "_exclusive").c_str(), (O_CREAT | O_EXCL), 0666, 0);
111 if (_exclusive_wake == SEM_FAILED)
112 throwex SystemException("Failed to create an exclusive wake semaphore for the named read/write lock!");
113 _shared_wake = sem_open((this->name() + "_shared").c_str(), (O_CREAT | O_EXCL), 0666, 0);
114 if (_shared_wake == SEM_FAILED)
115 throwex SystemException("Failed to create an shared wake semaphore for the named read/write lock!");
116 }
117 else
118 {
119 _exclusive_wake = sem_open((this->name() + "_exclusive").c_str(), O_CREAT, 0666, 0);
120 if (_exclusive_wake == SEM_FAILED)
121 throwex SystemException("Failed to open an exclusive wake semaphore for the named read/write lock!");
122 _shared_wake = sem_open((this->name() + "_shared").c_str(), O_CREAT, 0666, 0);
123 if (_shared_wake == SEM_FAILED)
124 throwex SystemException("Failed to open an shared wake semaphore for the named read/write lock!");
125 }
126#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
127 _exclusive_wake = CreateSemaphoreA(nullptr, 0, MAXLONG, (this->name() + "_exclusive").c_str());
128 if (_exclusive_wake == nullptr)
129 throwex SystemException("Failed to create or open an exclusive wake semaphore for the named read/write lock!");
130 _shared_wake = CreateSemaphoreA(nullptr, 0, MAXLONG, (this->name() + "_shared").c_str());
131 if (_shared_wake == nullptr)
132 throwex SystemException("Failed to create or open a shared wake semaphore for the named read/write lock!");
133#endif
134 }
135
136 ~Impl()
137 {
138#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
139 int result = sem_close(_exclusive_wake);
140 if (result != 0)
141 fatality(SystemException("Failed to close an exclusive wake semaphore for the named read/write lock"));
142 result = sem_close(_shared_wake);
143 if (result != 0)
144 fatality(SystemException("Failed to close an shared wake semaphore for the named read/write lock"));
145 // Unlink the named semaphores (owner only)
146 if (_value.owner())
147 {
148 result = sem_unlink((name() + "_exclusive").c_str());
149 if (result != 0)
150 fatality(SystemException("Failed to unlink an exclusive wake semaphore for the named read/write lock!"));
151 result = sem_unlink((name() + "_shared").c_str());
152 if (result != 0)
153 fatality(SystemException("Failed to unlink an shared wake semaphore for the named read/write lock!"));
154 }
155#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
156 if (!CloseHandle(_exclusive_wake))
157 fatality(SystemException("Failed to close an exclusive wake semaphore for the named read/write lock!"));
158 if (!CloseHandle(_shared_wake))
159 fatality(SystemException("Failed to close a shared wake semaphore for the named read/write lock!"));
160#endif
161 }
162
163 const std::string& name() const
164 {
165 return _value.name();
166 }
167
168 bool TryLockRead()
169 {
170 uint32_t value = (uint32_t)*_value;
171
172 if (value & LOCK_EXCLUSIVE_MASK)
173 return false;
174
175 if (!(value & LOCK_OWNED))
176 {
177#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
178 return __sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_OWNED + LOCK_SHARED_OWNERS_INC);
179#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
180 return (InterlockedCompareExchange(_value.ptr(), value + LOCK_OWNED + LOCK_SHARED_OWNERS_INC, value) == value);
181#endif
182 }
183 else if ((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK)
184 {
185#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
186 return __sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_SHARED_OWNERS_INC);
187#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
188 return (InterlockedCompareExchange(_value.ptr(), value + LOCK_SHARED_OWNERS_INC, value) == value);
189#endif
190 }
191 else
192 return false;
193 }
194
195 bool TryLockWrite()
196 {
197 uint32_t value = (uint32_t)*_value;
198
199 if (value & (LOCK_OWNED | LOCK_EXCLUSIVE_WAKING))
200 return false;
201
202#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
203 return __sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_OWNED);
204#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
205 return (InterlockedCompareExchange(_value.ptr(), value + LOCK_OWNED, value) == value);
206#endif
207 }
208
209 bool TryConvertWriteToRead()
210 {
211 while (true)
212 {
213 uint32_t value = (uint32_t)*_value;
214
215 // Can't convert if there are other shared owners
216 if (((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK) != 1)
217 return false;
218
219#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
220 if (__sync_bool_compare_and_swap(_value.ptr(), value, value - LOCK_SHARED_OWNERS_INC))
221#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
222 if (InterlockedCompareExchange(_value.ptr(), value - LOCK_SHARED_OWNERS_INC, value) == value)
223#endif
224 return true;
225 }
226 }
227
228 void LockRead()
229 {
230 uint32_t iteration = 0;
231
232 while (true)
233 {
234 uint32_t value = (uint32_t)*_value;
235
236 // Case 1: lock not owned AND no exclusive waiter is waking up AND
237 // there are no shared owners AND there are no exclusive waiters
238 if (!(value & (LOCK_OWNED | (LOCK_SHARED_OWNERS_MASK << LOCK_SHARED_OWNERS_SHIFT) | LOCK_EXCLUSIVE_MASK)))
239 {
240#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
241 if (__sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_OWNED + LOCK_SHARED_OWNERS_INC))
242#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
243 if (InterlockedCompareExchange(_value.ptr(), value + LOCK_OWNED + LOCK_SHARED_OWNERS_INC, value) == value)
244#endif
245 break;
246 }
247 // Case 2: lock is owned AND no exclusive waiter is waking up AND
248 // there are shared owners AND there are no exclusive waiters
249 else if ((value & LOCK_OWNED) && ((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK) > 0 && !(value & LOCK_EXCLUSIVE_MASK))
250 {
251#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
252 if (__sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_SHARED_OWNERS_INC))
253#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
254 if (InterlockedCompareExchange(_value.ptr(), value + LOCK_SHARED_OWNERS_INC, value) == value)
255#endif
256 break;
257 }
258 // Other cases
259 else if (iteration++ >= _spin)
260 {
261#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
262 if (__sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_SHARED_WAITERS_INC))
263#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
264 if (InterlockedCompareExchange(_value.ptr(), value + LOCK_SHARED_WAITERS_INC, value) == value)
265#endif
266 {
267 // Go to sleep
268#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
269 int result = sem_wait(_shared_wake);
270 if (result != 0)
271 throwex SystemException("Failed to wait for a shared wake semaphore for the named read/write lock!");
272#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
273 DWORD result = WaitForSingleObject(_shared_wake, INFINITE);
274 if (result != WAIT_OBJECT_0)
275 throwex SystemException("Failed to wait for a shared wake semaphore for the named read/write lock!");
276#endif
277 // Go back and try again
278 continue;
279 }
280 }
281
282 // Yield to other threads
283 Thread::Yield();
284 }
285 }
286
287 void LockWrite()
288 {
289 uint32_t iteration = 0;
290
291 while (true)
292 {
293 uint32_t value = (uint32_t)*_value;
294
295 // Case 1: lock not owned AND an exclusive waiter is not waking up.
296 // Here we don't have to check if there are exclusive waiters, because
297 // if there are the lock would be owned, and we are checking that anyway.
298 if (!(value & (LOCK_OWNED | LOCK_EXCLUSIVE_WAKING)))
299 {
300#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
301 if (__sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_OWNED))
302#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
303 if (InterlockedCompareExchange(_value.ptr(), value + LOCK_OWNED, value) == value)
304#endif
305 break;
306 }
307 // Case 2: lock owned OR lock not owned and an exclusive waiter is waking up.
308 // The second case means an exclusive waiter has just been woken up and is
309 // going to acquire the lock. We have to go to sleep to make sure we don't
310 // steal the lock.
311 else if (iteration++ >= _spin)
312 {
313#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
314 if (__sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_EXCLUSIVE_WAITERS_INC))
315#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
316 if (InterlockedCompareExchange(_value.ptr(), value + LOCK_EXCLUSIVE_WAITERS_INC, value) == value)
317#endif
318 {
319#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
320 int result = sem_wait(_exclusive_wake);
321 if (result != 0)
322 throwex SystemException("Failed to wait for an exclusive wake semaphore for the named read/write lock!");
323#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
324 DWORD result = WaitForSingleObject(_exclusive_wake, INFINITE);
325 if (result != WAIT_OBJECT_0)
326 throwex SystemException("Failed to wait for an exclusive wake semaphore for the named read/write lock!");
327#endif
328 // Acquire the lock.
329 // At this point *no one* should be able to steal the lock from us.
330 do
331 {
332 value = (uint32_t)*_value;
333#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
334 } while (!__sync_bool_compare_and_swap(_value.ptr(), value, value + LOCK_OWNED - LOCK_EXCLUSIVE_WAKING));
335#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
336 } while (InterlockedCompareExchange(_value.ptr(), value + LOCK_OWNED - LOCK_EXCLUSIVE_WAKING, value) != value);
337#endif
338 break;
339 }
340 }
341
342 // Yield to other threads
343 Thread::Yield();
344 }
345 }
346
347 void UnlockRead()
348 {
349 while (true)
350 {
351 uint32_t value = (uint32_t)*_value;
352
353 // Case 1: there are multiple shared owners
354 if (((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK) > 1)
355 {
356#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
357 if (__sync_bool_compare_and_swap(_value.ptr(), value, value - LOCK_SHARED_OWNERS_INC))
358#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
359 if (InterlockedCompareExchange(_value.ptr(), value - LOCK_SHARED_OWNERS_INC, value) == value)
360#endif
361 break;
362 }
363 // Case 2: we are the last shared owner AND there are exclusive waiters
364 else if ((value >> LOCK_EXCLUSIVE_WAITERS_SHIFT) & LOCK_EXCLUSIVE_WAITERS_MASK)
365 {
366#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
367 if (__sync_bool_compare_and_swap(_value.ptr(), value, value - LOCK_OWNED + LOCK_EXCLUSIVE_WAKING - LOCK_SHARED_OWNERS_INC - LOCK_EXCLUSIVE_WAITERS_INC))
368#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
369 if (InterlockedCompareExchange(_value.ptr(), value - LOCK_OWNED + LOCK_EXCLUSIVE_WAKING - LOCK_SHARED_OWNERS_INC - LOCK_EXCLUSIVE_WAITERS_INC, value) == value)
370#endif
371 {
372#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
373 int result = sem_post(_exclusive_wake);
374 if (result != 0)
375 throwex SystemException("Failed to release an exclusive wake semaphore for the named read/write lock!");
376#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
377 if (!ReleaseSemaphore(_exclusive_wake, 1, nullptr))
378 throwex SystemException("Failed to release an exclusive wake semaphore for the named read/write lock!");
379#endif
380 break;
381 }
382 }
383 // Case 3: we are the last shared owner AND there are no exclusive waiters
384 else
385 {
386#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
387 if (__sync_bool_compare_and_swap(_value.ptr(), value, value - LOCK_OWNED - LOCK_SHARED_OWNERS_INC))
388#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
389 if (InterlockedCompareExchange(_value.ptr(), value - LOCK_OWNED - LOCK_SHARED_OWNERS_INC, value) == value)
390#endif
391 break;
392 }
393
394 // Yield to other threads
396 }
397 }
398
399 void UnlockWrite()
400 {
401 while (true)
402 {
403 uint32_t value = (uint32_t)*_value;
404
405 // Case 1: if we have exclusive waiters, release one
406 if ((value >> LOCK_EXCLUSIVE_WAITERS_SHIFT) & LOCK_EXCLUSIVE_WAITERS_MASK)
407 {
408#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
409 if (__sync_bool_compare_and_swap(_value.ptr(), value, value - LOCK_OWNED + LOCK_EXCLUSIVE_WAKING - LOCK_EXCLUSIVE_WAITERS_INC))
410#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
411 if (InterlockedCompareExchange(_value.ptr(), value - LOCK_OWNED + LOCK_EXCLUSIVE_WAKING - LOCK_EXCLUSIVE_WAITERS_INC, value) == value)
412#endif
413 {
414#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
415 int result = sem_post(_exclusive_wake);
416 if (result != 0)
417 throwex SystemException("Failed to release an exclusive wake semaphore for the named read/write lock!");
418#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
419 if (!ReleaseSemaphore(_exclusive_wake, 1, nullptr))
420 throwex SystemException("Failed to release an exclusive wake semaphore for the named read/write lock!");
421#endif
422 break;
423 }
424 }
425 // Case 2: if we have shared waiters, release all of them
426 else
427 {
428 uint32_t shared_waiters = (value >> LOCK_SHARED_WAITERS_SHIFT) & LOCK_SHARED_WAITERS_MASK;
429
430#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
431 if (__sync_bool_compare_and_swap(_value.ptr(), value, value & ~(LOCK_OWNED | (LOCK_SHARED_WAITERS_MASK << LOCK_SHARED_WAITERS_SHIFT))))
432#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
433 if (InterlockedCompareExchange(_value.ptr(), value & ~(LOCK_OWNED | (LOCK_SHARED_WAITERS_MASK << LOCK_SHARED_WAITERS_SHIFT)), value) == value)
434#endif
435 {
436 if (shared_waiters > 0)
437 {
438#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
439 while (shared_waiters-- > 0)
440 {
441 int result = sem_post(_shared_wake);
442 if (result != 0)
443 throwex SystemException("Failed to release a shared wake semaphore for the named read/write lock!");
444 }
445#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
446 if (!ReleaseSemaphore(_shared_wake, shared_waiters, nullptr))
447 throwex SystemException("Failed to release a shared wake semaphore for the named read/write lock!");
448#endif
449 }
450 break;
451 }
452 }
453
454 // Yield to other threads
456 }
457 }
458
459 void ConvertWriteToRead()
460 {
461 while (true)
462 {
463 uint32_t value = (uint32_t)*_value;
464
465 uint32_t shared_waiters = (value >> LOCK_SHARED_WAITERS_SHIFT) & LOCK_SHARED_WAITERS_MASK;
466
467#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
468 if (__sync_bool_compare_and_swap(_value.ptr(), value, (value + LOCK_SHARED_OWNERS_INC) & ~(LOCK_SHARED_WAITERS_MASK << LOCK_SHARED_WAITERS_SHIFT)))
469#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
470 if (InterlockedCompareExchange(_value.ptr(), (value + LOCK_SHARED_OWNERS_INC) & ~(LOCK_SHARED_WAITERS_MASK << LOCK_SHARED_WAITERS_SHIFT), value) == value)
471#endif
472 {
473 if (shared_waiters > 0)
474 {
475#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
476 while (shared_waiters-- > 0)
477 {
478 int result = sem_post(_shared_wake);
479 if (result != 0)
480 throwex SystemException("Failed to release a shared wake semaphore for the named read/write lock!");
481 }
482#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
483 if (!ReleaseSemaphore(_shared_wake, shared_waiters, nullptr))
484 throwex SystemException("Failed to release a shared wake semaphore for the named read/write lock!");
485#endif
486 }
487
488 break;
489 }
490 }
491 }
492
493private:
495#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
496 sem_t* _exclusive_wake;
497 sem_t* _shared_wake;
498#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
499 HANDLE _exclusive_wake;
500 HANDLE _shared_wake;
501#endif
502 uint32_t _spin;
503};
504
506
508{
509 // Check implementation storage parameters
510 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
511 static_assert((StorageSize >= sizeof(Impl)), "NamedRWLock::StorageSize must be increased!");
512 static_assert(((StorageAlign % alignof(Impl)) == 0), "NamedRWLock::StorageAlign must be adjusted!");
513
514 // Create the implementation instance
515 new(&_storage)Impl(name, 4000);
516}
517
519{
520 // Delete the implementation instance
521 reinterpret_cast<Impl*>(&_storage)->~Impl();
522}
523
524const std::string& NamedRWLock::name() const { return impl().name(); }
525
526bool NamedRWLock::TryLockRead() { return impl().TryLockRead(); }
527bool NamedRWLock::TryLockWrite() { return impl().TryLockWrite(); }
528bool NamedRWLock::TryConvertWriteToRead() { return impl().TryConvertWriteToRead(); }
529
531{
532 // Calculate a finish timestamp
533 Timestamp finish = NanoTimestamp() + timespan;
534
535 // Try to acquire read lock at least one time
536 if (TryLockRead())
537 return true;
538 else
539 {
540 // Try lock or yield for the given timespan
541 while (NanoTimestamp() < finish)
542 {
543 if (TryLockRead())
544 return true;
545 else
547 }
548
549 // Failed to acquire read lock
550 return false;
551 }
552}
553
555{
556 // Calculate a finish timestamp
557 Timestamp finish = NanoTimestamp() + timespan;
558
559 // Try to acquire write lock at least one time
560 if (TryLockWrite())
561 return true;
562 else
563 {
564 // Try lock or yield for the given timespan
565 while (NanoTimestamp() < finish)
566 {
567 if (TryLockWrite())
568 return true;
569 else
571 }
572
573 // Failed to acquire write lock
574 return false;
575 }
576}
577
579{
580 // Calculate a finish timestamp
581 Timestamp finish = NanoTimestamp() + timespan;
582
583 // Try to convert write lock to read lock at least one time
585 return true;
586 else
587 {
588 // Try convert write lock to read lock or yield for the given timespan
589 while (NanoTimestamp() < finish)
590 {
592 return true;
593 else
595 }
596
597 // Failed to convert write lock to read lock
598 return false;
599 }
600}
601
602void NamedRWLock::LockRead() { impl().LockRead(); }
603void NamedRWLock::LockWrite() { impl().LockWrite(); }
604void NamedRWLock::UnlockRead() { impl().UnlockRead(); }
605void NamedRWLock::UnlockWrite() { impl().UnlockWrite(); }
606void NamedRWLock::ConvertWriteToRead() { impl().ConvertWriteToRead(); }
607
608} // namespace CppCommon
void UnlockRead()
Release read lock.
void UnlockWrite()
Release write lock.
bool TryConvertWriteToRead()
Try to convert write lock to read lock without block.
bool TryLockReadFor(const Timespan &timespan)
Try to acquire read lock for the given timespan.
void LockRead()
Acquire read lock with block.
bool TryLockWrite()
Try to acquire write lock without block.
void ConvertWriteToRead()
Convert write lock to read lock without block.
bool TryLockRead()
Try to acquire read lock without block.
bool TryLockWriteFor(const Timespan &timespan)
Try to acquire write lock for the given timespan.
void LockWrite()
Acquire write lock with block.
NamedRWLock(const std::string &name)
Default class constructor.
const std::string & name() const
Get the read/write lock name.
bool TryConvertWriteToReadFor(const Timespan &timespan)
Try to convert write lock to read lock for the given timespan.
High resolution timestamp.
Definition timestamp.h:272
Shared memory type.
Definition shared_type.h:28
System exception.
Definition exceptions.h:107
static void Yield() noexcept
Yield to other threads.
Definition thread.cpp:143
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition fatal.h:22
Named read/write lock synchronization primitive definition.
C++ Common project definitions.
Semaphore synchronization primitive definition.
Shared memory type definition.
Thread definition.
Aligned storage validator definition.