16 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
19 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
82 class NamedRWLock::Impl
84 const uint32_t LOCK_OWNED = 0x1;
85 const uint32_t LOCK_EXCLUSIVE_WAKING = 0x2;
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;
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;
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;
99 const uint32_t LOCK_EXCLUSIVE_MASK = (LOCK_EXCLUSIVE_WAKING | (LOCK_EXCLUSIVE_WAITERS_MASK << LOCK_EXCLUSIVE_WAITERS_SHIFT));
102 Impl(
const std::string&
name, uint32_t spin) : _value(
name), _spin(spin)
107 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
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!");
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!");
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!");
138 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
139 int result = sem_close(_exclusive_wake);
141 fatality(SystemException(
"Failed to close an exclusive wake semaphore for the named read/write lock"));
142 result = sem_close(_shared_wake);
144 fatality(SystemException(
"Failed to close an shared wake semaphore for the named read/write lock"));
148 result = sem_unlink((
name() +
"_exclusive").c_str());
150 fatality(SystemException(
"Failed to unlink an exclusive wake semaphore for the named read/write lock!"));
151 result = sem_unlink((
name() +
"_shared").c_str());
153 fatality(SystemException(
"Failed to unlink an shared wake semaphore for the named read/write lock!"));
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!"));
163 const std::string&
name()
const
165 return _value.name();
170 uint32_t value = (uint32_t)*_value;
172 if (value & LOCK_EXCLUSIVE_MASK)
175 if (!(value & LOCK_OWNED))
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);
183 else if ((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK)
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);
197 uint32_t value = (uint32_t)*_value;
199 if (value & (LOCK_OWNED | LOCK_EXCLUSIVE_WAKING))
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);
213 uint32_t value = (uint32_t)*_value;
216 if (((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK) != 1)
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)
230 uint32_t iteration = 0;
234 uint32_t value = (uint32_t)*_value;
238 if (!(value & (LOCK_OWNED | (LOCK_SHARED_OWNERS_MASK << LOCK_SHARED_OWNERS_SHIFT) | LOCK_EXCLUSIVE_MASK)))
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)
249 else if ((value & LOCK_OWNED) && ((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK) > 0 && !(value & LOCK_EXCLUSIVE_MASK))
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)
259 else if (iteration++ >= _spin)
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)
268 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
269 int result = sem_wait(_shared_wake);
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!");
289 uint32_t iteration = 0;
293 uint32_t value = (uint32_t)*_value;
298 if (!(value & (LOCK_OWNED | LOCK_EXCLUSIVE_WAKING)))
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)
311 else if (iteration++ >= _spin)
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)
319 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
320 int result = sem_wait(_exclusive_wake);
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!");
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);
351 uint32_t value = (uint32_t)*_value;
354 if (((value >> LOCK_SHARED_OWNERS_SHIFT) & LOCK_SHARED_OWNERS_MASK) > 1)
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)
364 else if ((value >> LOCK_EXCLUSIVE_WAITERS_SHIFT) & LOCK_EXCLUSIVE_WAITERS_MASK)
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)
372 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
373 int result = sem_post(_exclusive_wake);
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!");
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)
403 uint32_t value = (uint32_t)*_value;
406 if ((value >> LOCK_EXCLUSIVE_WAITERS_SHIFT) & LOCK_EXCLUSIVE_WAITERS_MASK)
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)
414 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
415 int result = sem_post(_exclusive_wake);
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!");
428 uint32_t shared_waiters = (value >> LOCK_SHARED_WAITERS_SHIFT) & LOCK_SHARED_WAITERS_MASK;
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)
436 if (shared_waiters > 0)
438 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
439 while (shared_waiters-- > 0)
441 int result = sem_post(_shared_wake);
443 throwex SystemException(
"Failed to release a shared wake semaphore for the named read/write lock!");
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!");
459 void ConvertWriteToRead()
463 uint32_t value = (uint32_t)*_value;
465 uint32_t shared_waiters = (value >> LOCK_SHARED_WAITERS_SHIFT) & LOCK_SHARED_WAITERS_MASK;
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)
473 if (shared_waiters > 0)
475 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
476 while (shared_waiters-- > 0)
478 int result = sem_post(_shared_wake);
480 throwex SystemException(
"Failed to release a shared wake semaphore for the named read/write lock!");
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!");
494 SharedType<volatile uint64_t> _value;
495 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
496 sem_t* _exclusive_wake;
498 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
499 HANDLE _exclusive_wake;
507 NamedRWLock::NamedRWLock(
const std::string& name)
511 static_assert((StorageSize >=
sizeof(Impl)),
"NamedRWLock::StorageSize must be increased!");
512 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"NamedRWLock::StorageAlign must be adjusted!");
515 new(&_storage)Impl(name, 4000);
518 NamedRWLock::~NamedRWLock()
521 reinterpret_cast<Impl*
>(&_storage)->~Impl();
524 const std::string& NamedRWLock::name()
const {
return impl().name(); }
526 bool NamedRWLock::TryLockRead() {
return impl().TryLockRead(); }
527 bool NamedRWLock::TryLockWrite() {
return impl().TryLockWrite(); }
528 bool NamedRWLock::TryConvertWriteToRead() {
return impl().TryConvertWriteToRead(); }
530 bool NamedRWLock::TryLockReadFor(
const Timespan& timespan)
554 bool NamedRWLock::TryLockWriteFor(
const Timespan& timespan)
578 bool NamedRWLock::TryConvertWriteToReadFor(
const Timespan& timespan)
584 if (TryConvertWriteToRead())
591 if (TryConvertWriteToRead())
602 void NamedRWLock::LockRead() { impl().LockRead(); }
603 void NamedRWLock::LockWrite() { impl().LockWrite(); }
604 void NamedRWLock::UnlockRead() { impl().UnlockRead(); }
605 void NamedRWLock::UnlockWrite() { impl().UnlockWrite(); }
606 void NamedRWLock::ConvertWriteToRead() { impl().ConvertWriteToRead(); }
bool TryConvertWriteToRead()
Try to convert write lock to read lock without block.
void LockRead()
Acquire read lock with block.
bool TryLockWrite()
Try to acquire write lock without block.
bool TryLockRead()
Try to acquire read lock without block.
void LockWrite()
Acquire write lock with block.
const std::string & name() const
Get the read/write lock name.
High resolution timestamp.
static void Yield() noexcept
Yield to other threads.
Aligned storage validator.
#define throwex
Throw extended exception macro.
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Named read/write lock synchronization primitive definition.
C++ Common project definitions.
Semaphore synchronization primitive definition.
Shared memory type definition.
Aligned storage validator definition.