16#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
19#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
82class 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);
209 bool TryConvertWriteToRead()
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;
507NamedRWLock::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);
518NamedRWLock::~NamedRWLock()
521 reinterpret_cast<Impl*
>(&_storage)->~Impl();
524const std::string& NamedRWLock::name()
const {
return impl().name(); }
526bool NamedRWLock::TryLockRead() {
return impl().TryLockRead(); }
527bool NamedRWLock::TryLockWrite() {
return impl().TryLockWrite(); }
528bool NamedRWLock::TryConvertWriteToRead() {
return impl().TryConvertWriteToRead(); }
530bool NamedRWLock::TryLockReadFor(
const Timespan& timespan)
554bool NamedRWLock::TryLockWriteFor(
const Timespan& timespan)
578bool NamedRWLock::TryConvertWriteToReadFor(
const Timespan& timespan)
584 if (TryConvertWriteToRead())
591 if (TryConvertWriteToRead())
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(); }
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.