s_WriteMutexEvent(
void* mutex_ptr,
const char* message);
89 # define WRITE_MUTEX_EVENT(mutex, message) s_WriteMutexEvent(mutex, message) 93 # define WRITE_MUTEX_EVENT(mutex, message) ((void)0) 99 #if defined(_DEBUG) && defined(LOG_MUTEX_EVENTS) 101 voids_WriteMutexEvent(
void* mutex_ptr,
const char* message)
103 static const int mode= O_WRONLY | O_APPEND | O_CREAT;
109 static const char*
file_name= getenv(
"MUTEX_EVENTS_LOG_FILE");
122str_os << mutex_ptr <<
" " 125write(handle, str_os.str(), str_os.pcount());
126str_os.rdbuf()->freeze(
false);
136 voidSSystemFastMutex::InitializeHandle(
void)
141 #if defined(NCBI_WIN32_THREADS) 142 # if defined(NCBI_FASTMUTEX_USE_NEW) 143InitializeSRWLock(&m_Handle);
144 # elif defined(NCBI_USE_CRITICAL_SECTION) 145InitializeCriticalSection(&m_Handle);
149 "Mutex creation failed");
151 #elif defined(NCBI_POSIX_THREADS) 152 # if defined(NCBI_OS_CYGWIN) 153 if(pthread_mutex_init(&m_Handle, 0) != 0) {
158memset(&m_Handle, 0,
sizeof(m_Handle));
161 "Mutex creation failed");
162 # if defined(NCBI_OS_CYGWIN) 168 voidSSystemFastMutex::DestroyHandle(
void)
173 #if defined(NCBI_WIN32_THREADS) 174 # if defined(NCBI_FASTMUTEX_USE_NEW) 176 # elif defined(NCBI_USE_CRITICAL_SECTION) 177DeleteCriticalSection(&m_Handle);
181 #elif defined(NCBI_POSIX_THREADS) 186 voidSSystemFastMutex::InitializeStatic(
void)
188 #if !defined(NCBI_NO_THREADS) 190 caseeMutexUninitialized:
192 caseeMutexInitialized:
196 xncbi_Validate(0,
"SSystemFastMutex::m_Magic contains invalid value");
203m_Magic = eMutexInitialized;
207 voidSSystemFastMutex::InitializeDynamic(
void)
209 #if !defined(NCBI_NO_THREADS) 213m_Magic = eMutexInitialized;
217 voidSSystemFastMutex::Destroy(
void)
219 #if !defined(NCBI_NO_THREADS) 220 xncbi_Validate(IsInitialized(),
"Destruction of uninitialized mutex");
223m_Magic = eMutexUninitialized;
228 voidSSystemFastMutex::ThrowUninitialized(
void)
233 voidSSystemFastMutex::ThrowLockFailed(
void)
238 voidSSystemFastMutex::ThrowUnlockFailed(
void)
243 voidSSystemFastMutex::ThrowTryLockFailed(
void)
246 "Mutex check (TryLock) failed");
249 voidSSystemMutex::Destroy(
void)
255 #if !defined(NCBI_NO_THREADS) 262 if(lock != eNormal) {
267 # if defined(NCBI_WIN32_THREADS) 268 # if defined(NCBI_FASTMUTEX_USE_NEW) 269AcquireSRWLockExclusive(&m_Handle);
270 # elif defined(NCBI_USE_CRITICAL_SECTION) 271EnterCriticalSection(&m_Handle);
273 if(WaitForSingleObject(m_Handle, INFINITE) != WAIT_OBJECT_0) {
277 # elif defined(NCBI_POSIX_THREADS) 278 if( pthread_mutex_lock(&m_Handle) != 0 ) {
284 boolSSystemFastMutex::TryLock(
void)
293 # if defined(NCBI_WIN32_THREADS) 294 # if defined(NCBI_FASTMUTEX_USE_NEW) 295 returnTryAcquireSRWLockExclusive(&m_Handle) != 0;
296 # elif defined(NCBI_USE_CRITICAL_SECTION) 297 returnTryEnterCriticalSection(&m_Handle) != 0;
299 DWORDstatus = WaitForSingleObject(m_Handle, 0);
300 if(status == WAIT_OBJECT_0) {
304 if(status != WAIT_TIMEOUT) {
305ThrowTryLockFailed();
310 # elif defined(NCBI_POSIX_THREADS) 311 intstatus = pthread_mutex_trylock(&m_Handle);
316 if(status != EBUSY) {
317ThrowTryLockFailed();
330 if(lock != eNormal) {
335 # if defined(NCBI_WIN32_THREADS) 336 # if defined(NCBI_FASTMUTEX_USE_NEW) 337ReleaseSRWLockExclusive(&m_Handle);
338 # elif defined(NCBI_USE_CRITICAL_SECTION) 339LeaveCriticalSection(&m_Handle);
341 if( !ReleaseMutex(m_Handle) ) {
345 # elif defined(NCBI_POSIX_THREADS) 346 if( pthread_mutex_unlock(&m_Handle) != 0 ) {
354m_Mutex.CheckInitialized();
357 auto count= m_Count.load(memory_order_acquire);
358 if(
count> 0 && m_Owner.load(memory_order_relaxed) == owner ) {
360m_Count.store(++
count, memory_order_release);
367m_Owner.store(owner, memory_order_relaxed);
368m_Count.store(1, memory_order_release);
371 boolSSystemMutex::TryLock(
void)
373m_Mutex.CheckInitialized();
376 auto count= m_Count.load(memory_order_acquire);
377 if(
count> 0 && m_Owner.load(memory_order_relaxed) == owner ) {
379m_Count.store(++
count, memory_order_release);
384 if( m_Mutex.TryLock() ) {
385 assert(m_Count.load(memory_order_relaxed) == 0);
386m_Owner.store(owner, memory_order_relaxed);
387m_Count.store(1, memory_order_release);
397m_Mutex.CheckInitialized();
402 auto count= m_Count.load(memory_order_acquire);
403 if(
count== 0 || m_Owner.load(memory_order_relaxed) != owner ) {
408m_Count.store(--
count, memory_order_release);
414m_Mutex.Unlock(lock);
418 voidSSystemMutex::ThrowNotOwned(
void)
421 "Mutex is not owned by current thread");
425 #if defined(NEED_AUTO_INITIALIZE_MUTEX) 428 static const char* kInitMutexName =
"NCBI_CAutoInitializeStaticMutex";
430 #ifdef USE_STATIC_INIT_MUTEX_HANDLE 437init_mutex = CreateMutex(
NULL,
FALSE, kInitMutexName);
439 assert(!s_InitMutexHandle || s_InitMutexHandle == init_mutex);
440s_InitMutexHandle = init_mutex;
447 assert(mutex == s_InitMutexHandle);
452 static inline HANDLEs_GetInitMutexHandle(
void)
459 static inline voids_ReleaseInitMutexHandle(
HANDLEmutex)
466 voidCAutoInitializeStaticFastMutex::Initialize(
void)
468 if( m_Mutex.IsInitialized() ) {
471 HANDLEinit_mutex = s_GetInitMutexHandle();
473WaitForSingleObject(init_mutex, INFINITE) == WAIT_OBJECT_0);
474 if( !m_Mutex.IsInitialized() ) {
475m_Mutex.InitializeStatic();
478 assert(m_Mutex.IsInitialized());
479s_ReleaseInitMutexHandle(init_mutex);
482 voidCAutoInitializeStaticMutex::Initialize(
void)
484 if( m_Mutex.IsInitialized() ) {
487 HANDLEinit_mutex = s_GetInitMutexHandle();
489WaitForSingleObject(init_mutex, INFINITE) == WAIT_OBJECT_0);
490 if( !m_Mutex.IsInitialized() ) {
491m_Mutex.InitializeStatic();
494 assert(m_Mutex.IsInitialized());
495s_ReleaseInitMutexHandle(init_mutex);
503 case eLock:
return "eLock";
504 case eUnlock:
return "eUnlock";
506 case eOwner:
return "eOwner";
516 #if defined(NCBI_WIN32_THREADS) && !NCBI_SRWLOCK_USE_NEW 521CWindowsHandle(
HANDLEh =
NULL) : m_Handle(h) {}
522CWindowsHandle(
HANDLEh,
const char* errorMessage) : m_Handle(h)
526~CWindowsHandle(
void) { Close(); }
530 if( m_Handle !=
NULL) {
531CloseHandle(m_Handle);
541 voidSet(
HANDLEh,
const char* errorMessage)
547 HANDLEGetHandle(
void)
const{
returnm_Handle; }
548 operator HANDLE(
void)
const{
returnm_Handle; }
554CWindowsHandle(
constCWindowsHandle& h);
555CWindowsHandle& operator=(
constCWindowsHandle& h);
558 classCWindowsSemaphore :
publicCWindowsHandle
561CWindowsSemaphore(LONG initialCount = 0, LONG maximumCount = INFINITE)
562: CWindowsHandle(CreateSemaphore(
NULL,
563initialCount, maximumCount,
565 "CreateSemaphore() failed")
569LONG Release(LONG add = 1)
573 "CWindowsSemaphore::Release() failed");
580 #if defined(NCBI_POSIX_THREADS) 596 operatorpthread_cond_t*(void) {
return&
m_Handle; }
597 operatorpthread_cond_t&(void) {
return m_Handle; }
606 #if !NCBI_SRWLOCK_USE_NEW 613 #if defined(NCBI_WIN32_THREADS) 614CWindowsSemaphore m_Rsema;
615CWindowsSemaphore m_Rsema2;
616CWindowsSemaphore m_Wsema;
617 # if defined(NCBI_USE_CRITICAL_SECTION) 622 #elif defined(NCBI_POSIX_THREADS) 631 #if defined(NCBI_WIN32_THREADS) 632: m_Rsema(1, 1), m_Rsema2(1, 1), m_Wsema(1, 1)
635 #if defined(NCBI_USE_CRITICAL_SECTION) 644 #if NCBI_SRWLOCK_USE_NEW 646: m_Owner(0), m_Count(0), m_WaitingWriters(0), m_TrackReaders(
false)
649m_TrackReaders =
true;
650m_FavorWriters = (
flags& fFavorWriters) != 0;
652m_TrackReaders = m_FavorWriters = (
flags& fFavorWriters) != 0;
654 if(m_TrackReaders) {
655m_Readers.reserve(16);
685 #if NCBI_SRWLOCK_USE_NEW 687vector<TThreadSystemID>::const_iterator
707 boolCRWLock::x_TryWriteLock()
714 boolCRWLock::x_TryReadLock()
743 #if defined(NCBI_USE_CRITICAL_SECTION) && !NCBI_SRWLOCK_USE_NEW 746 classCWin32MutexHandleGuard
749CWin32MutexHandleGuard(
HANDLEmutex);
750~CWin32MutexHandleGuard(
void);
757CWin32MutexHandleGuard::CWin32MutexHandleGuard(
HANDLEmutex)
760WaitForSingleObject(m_Handle, INFINITE);
765CWin32MutexHandleGuard::~CWin32MutexHandleGuard(
void)
767ReleaseMutex(m_Handle);
778 #if defined(NCBI_WIN32_THREADS) 779 for(
longold_val = *
val; ; old_val = *
val) {
780 longcur_val = InterlockedCompareExchange(
val, new_val, old_val);
781 if(cur_val == old_val) {
793 #if defined(NCBI_WIN32_THREADS) 794 for(
longold_val = *
val; old_val >
min; old_val = *
val) {
795 longnew_val = old_val + 1;
796 longcur_val = InterlockedCompareExchange(
val, new_val, old_val);
797 if(cur_val == old_val) {
811 #if defined(NCBI_WIN32_THREADS) 812 for(
longold_val = *
val; old_val <
max; old_val = *
val) {
813 longnew_val = old_val + 1;
814 longcur_val = InterlockedCompareExchange(
val, new_val, old_val);
815 if(cur_val == old_val) {
829 #if defined(NCBI_WIN32_THREADS) 830 for(
longold_val = *
val; old_val <
max; old_val = *
val) {
831 longnew_val = old_val - 1;
832 longcur_val = InterlockedCompareExchange(
val, new_val, old_val);
833 if(cur_val == old_val) {
847 #if defined(NCBI_WIN32_THREADS) 848 for(
longold_val = *
val; old_val >
min; old_val = *
val) {
849 longnew_val = old_val - 1;
850 longcur_val = InterlockedCompareExchange(
val, new_val, old_val);
851 if(cur_val == old_val) {
865 #if defined(NCBI_NO_THREADS) 869 #if NCBI_SRWLOCK_USE_NEW 874 if(!m_TrackReaders && x_TryReadLock()) {
877unique_lock<mutex> lck( m_Mtx);
884}
while(!x_TryReadLock());
885 if(m_TrackReaders) {
891 #if defined(NCBI_WIN32_THREADS) 902 #if defined(NCBI_USE_CRITICAL_SECTION) 903CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
913 #if defined(NCBI_WIN32_THREADS) 915obj[0] =
m_RW->m_Mutex.GetHandle();
916obj[1] =
m_RW->m_Rsema;
917obj[2] =
m_RW->m_Rsema2;
919ReleaseMutex(
m_RW->m_Mutex.GetHandle()),
920 "CRWLock::ReadLock() - release mutex error");
922WaitForMultipleObjects(3, obj,
TRUE, INFINITE)-WAIT_OBJECT_0;
924 "CRWLock::ReadLock() - R-lock waiting error");
927&&
m_RW->m_Rsema2.Release() == 0,
928 "CRWLock::ReadLock() - invalid R-semaphore state");
932 "CRWLock::ReadLock() - " 933 "failed to lock W-semaphore");
935 #elif defined(NCBI_POSIX_THREADS) 938pthread_cond_wait(
m_RW->m_Rcond,
939 m_RW->m_Mutex.GetHandle()), 0,
940 "CRWLock::ReadLock() - R-lock waiting error");
945 "CRWLock::ReadLock() - " 946 "weird R-lock error in non-MT mode");
949 "CRWLock::ReadLock() - invalid readers counter");
954 #if defined(NCBI_WIN32_THREADS) 960 "CRWLock::ReadLock() - " 961 "can not lock W-semaphore");
978 #if defined(NCBI_NO_THREADS) 982 #if NCBI_SRWLOCK_USE_NEW 987 if(!m_TrackReaders && x_TryReadLock()) {
990unique_lock<mutex> lck( m_Mtx);
994 if(!x_TryReadLock()) {
997 if(m_TrackReaders) {
1004 #if defined(NCBI_WIN32_THREADS) 1012 #if defined(NCBI_USE_CRITICAL_SECTION) 1013CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
1031 #if defined(NCBI_WIN32_THREADS) 1036 "CRWLock::TryReadLock() - " 1037 "can not lock W-semaphore");
1052 #if defined(NCBI_NO_THREADS) 1060 if( timeout.
IsZero() ) {
1064 #if NCBI_SRWLOCK_USE_NEW 1069 if(!m_TrackReaders && x_TryReadLock()) {
1072 unsigned intsec=0, nanosec=0;
1073timeout.
GetNano(&sec, &nanosec);
1074chrono::time_point<chrono::steady_clock> to = chrono::steady_clock::now() + chrono::seconds(sec) + chrono::nanoseconds(nanosec);
1075cv_status res = cv_status::no_timeout;
1078unique_lock<mutex> lck( m_Mtx);
1080 if(res == cv_status::timeout) {
1085res = m_Cv.wait_until(lck, to);
1091}
while(!x_TryReadLock());
1092 if(m_TrackReaders) {
1099 #if defined(NCBI_WIN32_THREADS) 1110 #if defined(NCBI_USE_CRITICAL_SECTION) 1111CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
1121 #if defined(NCBI_WIN32_THREADS) 1123obj[0] =
m_RW->m_Mutex.GetHandle();
1124obj[1] =
m_RW->m_Rsema;
1125obj[2] =
m_RW->m_Rsema2;
1127ReleaseMutex(
m_RW->m_Mutex.GetHandle()),
1128 "CRWLock::TryReadLock() - release mutex error");
1131WaitForMultipleObjects(3, obj,
TRUE, timeout_msec);
1132 if(wait_res == WAIT_TIMEOUT) {
1135wait_res -= WAIT_OBJECT_0;
1137 "CRWLock::TryReadLock() - R-lock waiting error");
1140&&
m_RW->m_Rsema2.Release() == 0,
1141 "CRWLock::TryReadLock() - invalid R-semaphore state");
11440) == WAIT_OBJECT_0,
1145 "CRWLock::TryReadLock() - " 1146 "failed to lock W-semaphore");
1148 #elif defined(NCBI_POSIX_THREADS) 1158res = pthread_cond_timedwait(
m_RW->m_Rcond,
1159 m_RW->m_Mutex.GetHandle(), &ts);
1161 if(res == ETIMEDOUT) {
1165 "CRWLock::TryReadLock() - R-lock waiting error");
1169 "CRWLock::TryReadLock() - " 1170 "weird R-lock error in non-MT mode");
1173 "CRWLock::TryReadLock() - invalid readers counter");
1178 #if defined(NCBI_WIN32_THREADS) 1184 "CRWLock::TryReadLock() - " 1185 "can not lock W-semaphore");
1203 #if defined(NCBI_NO_THREADS) 1207 #if NCBI_SRWLOCK_USE_NEW 1212 if(x_TryWriteLock()) {
1216unique_lock<mutex> lck( m_Mtx);
1217 _ASSERT(!m_TrackReaders || !x_HasReader(self_id));
1218 if(m_FavorWriters) {
1221 while(!x_TryWriteLock()) {
1225 if(m_FavorWriters) {
1233 #if defined(NCBI_USE_CRITICAL_SECTION) 1234CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
1248 "CRWLock::WriteLock() - " 1249 "attempt to set W-after-R lock");
1251 #if defined(NCBI_WIN32_THREADS) 1253obj[0] =
m_RW->m_Rsema;
1254obj[1] =
m_RW->m_Wsema;
1255obj[2] =
m_RW->m_Mutex.GetHandle();
1259WaitForMultipleObjects(2, obj,
TRUE, 0)-WAIT_OBJECT_0;
1261 "CRWLock::WriteLock() - " 1262 "error locking R&W-semaphores");
1271 "CRWLock::WriteLock() - " 1272 "error locking R-semaphore 2");
1276ReleaseMutex(
m_RW->m_Mutex.GetHandle()),
1277 "CRWLock::WriteLock() - release mutex error");
1279WaitForMultipleObjects(3, obj,
TRUE, INFINITE)-WAIT_OBJECT_0;
1281 "CRWLock::WriteLock() - " 1282 "error locking R&W-semaphores");
1286 "CRWLock::WriteLock() - " 1287 "invalid R-semaphore 2 state");
1293 #elif defined(NCBI_POSIX_THREADS) 1299pthread_cond_wait(
m_RW->m_Wcond,
1300 m_RW->m_Mutex.GetHandle()), 0,
1301 "CRWLock::WriteLock() - error locking R&W-conditionals");
1308 "CRWLock::WriteLock() - invalid readers counter");
1322 #if defined(NCBI_NO_THREADS) 1326 #if NCBI_SRWLOCK_USE_NEW 1331 if(!x_TryWriteLock()) {
1341 #if defined(NCBI_USE_CRITICAL_SECTION) 1342CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
1362 #if defined(NCBI_WIN32_THREADS) 1365obj[0] =
m_RW->m_Rsema;
1366obj[1] =
m_RW->m_Wsema;
1368WaitForMultipleObjects(2, obj,
TRUE, 0) - WAIT_OBJECT_0;
1370 "CRWLock::TryWriteLock() - " 1371 "error locking R&W-semaphores");
1388 #if defined(NCBI_NO_THREADS) 1396 if( timeout.
IsZero() ) {
1400 #if NCBI_SRWLOCK_USE_NEW 1405 if(x_TryWriteLock()) {
1409 unsigned intsec=0, nanosec=0;
1410timeout.
GetNano(&sec, &nanosec);
1411chrono::time_point<chrono::steady_clock> to = chrono::steady_clock::now() + chrono::seconds(sec) + chrono::nanoseconds(nanosec);
1412cv_status res = cv_status::no_timeout;
1415unique_lock<mutex> lck( m_Mtx);
1417 if(res == cv_status::timeout) {
1420 if(m_FavorWriters) {
1423 while(!(
ok=
m_Count== 0) && res == cv_status::no_timeout) {
1424res = m_Cv.wait_until(lck, to);
1426 if(m_FavorWriters) {
1432}
while(!x_TryWriteLock());
1439 #if defined(NCBI_USE_CRITICAL_SECTION) 1440CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
1454 "CRWLock::TryWriteLock() - " 1455 "attempt to set W-after-R lock");
1457 #if defined(NCBI_WIN32_THREADS) 1459obj[0] =
m_RW->m_Rsema;
1460obj[1] =
m_RW->m_Wsema;
1461obj[2] =
m_RW->m_Mutex.GetHandle();
1465WaitForMultipleObjects(2, obj,
TRUE, 0)-WAIT_OBJECT_0;
1467 "CRWLock::TryWriteLock() - " 1468 "error locking R&W-semaphores");
1477 "CRWLock::TryWriteLock() - " 1478 "error locking R-semaphore 2");
1482ReleaseMutex(
m_RW->m_Mutex.GetHandle()),
1483 "CRWLock::TryWriteLock() - release mutex error");
1486WaitForMultipleObjects(3, obj,
TRUE, timeout_msec);
1487 if(wait_res == WAIT_TIMEOUT) {
1490CWin32MutexHandleGuard counter_guard(
m_RW->m_Mutex);
1493 "CRWLock::TryWriteLock() - " 1494 "invalid R-semaphore 2 state");
1501wait_res -= WAIT_OBJECT_0;
1503 "CRWLock::TryWriteLock() - " 1504 "error locking R&W-semaphores");
1508 "CRWLock::TryWriteLock() - " 1509 "invalid R-semaphore 2 state");
1515 #elif defined(NCBI_POSIX_THREADS) 1527 while(
m_Count!= 0 && res != ETIMEDOUT ) {
1528res = pthread_cond_timedwait(
m_RW->m_Wcond,
1529 m_RW->m_Mutex.GetHandle(), &ts);
1531 if(res == ETIMEDOUT) {
1538 "CRWLock::TryWriteLock() - " 1539 "error locking R&W-conditionals");
1545 "CRWLock::TryWriteLock() - invalid readers counter");
1560 #if defined(NCBI_NO_THREADS) 1564 #if NCBI_SRWLOCK_USE_NEW 1570unique_lock<mutex> lck( m_Mtx
);
1577 if(m_TrackReaders) {
1579 m_Readers.erase( x_FindReader(self_id) );
1580}
else if(
cnt!= 0) {
1587 #if defined(NCBI_WIN32_THREADS) 1595 #if defined(NCBI_USE_CRITICAL_SECTION) 1596CWin32MutexHandleGuard guard(
m_RW->m_Mutex);
1604 "CRWLock::Unlock() - " 1605 "RWLock is locked by another thread");
1609 #if defined(NCBI_WIN32_THREADS) 1611 "CRWLock::Unlock() - invalid R-semaphore state");
1613 "CRWLock::Unlock() - invalid R-semaphore state");
1614 #elif defined(NCBI_POSIX_THREADS) 1617pthread_cond_broadcast(
m_RW->m_Rcond), 0,
1618 "CRWLock::Unlock() - error signalling unlock");
1621pthread_cond_signal(
m_RW->m_Wcond), 0,
1622 "CRWLock::Unlock() - error signalling unlock");
1633 "CRWLock::Unlock() - RWLock is not locked");
1637 #if defined(NCBI_WIN32_THREADS) 1639 "CRWLock::Unlock() - invalid W-semaphore state");
1640 #elif defined(NCBI_POSIX_THREADS) 1642pthread_cond_signal(
m_RW->m_Wcond), 0,
1643 "CRWLock::Unlock() - error signaling unlock");
1648vector<TThreadSystemID>::iterator found =
1672 #if defined(NCBI_POSIX_THREADS) 1679 #elif defined(NCBI_WIN32_THREADS) 1683 unsigned int count;
1688 #if NCBI_SEMAPHORE_USE_NEW 1690: m_Max(max_count), m_Count(init_count)
1698 #if defined(NCBI_WIN32_THREADS) 1700max_count =
min(max_count, (
unsigned int)LONG_MAX);
1703 "CSemaphore::CSemaphore() - max_count passed zero");
1705 "CSemaphore::CSemaphore() - init_count " 1706 "greater than max_count");
1709unique_ptr<SSemaphore> auto_sem(
m_Sem);
1711 #if defined(NCBI_POSIX_THREADS) 1716 # if defined(NCBI_OS_CYGWIN) 1717 if(pthread_mutex_init(&
m_Sem->
mutex, 0) != 0) {
1722 "CSemaphore::CSemaphore() - pthread_mutex_init() failed");
1723 # if defined(NCBI_OS_CYGWIN) 1727 # if defined(NCBI_OS_CYGWIN) 1728 if(pthread_cond_init(&
m_Sem->
cond, 0) != 0) {
1732pthread_cond_init(&
m_Sem->
cond, 0), 0,
1733 "CSemaphore::CSemaphore() - pthread_cond_init() failed");
1734 # if defined(NCBI_OS_CYGWIN) 1738 #elif defined(NCBI_WIN32_THREADS) 1739 m_Sem->sem = CreateSemaphore(
NULL, init_count, max_count,
NULL);
1742 DWORDdwErr = GetLastError();
1747 "CSemaphore::CSemaphore() - CreateSemaphore() failed");
1760 #if NCBI_SEMAPHORE_USE_NEW 1762 #if defined(NCBI_POSIX_THREADS) 1767 #elif defined(NCBI_WIN32_THREADS) 1775 #if NCBI_SEMAPHORE_USE_NEW 1777 boolCSemaphore::x_TryAcquire(
void)
1789 #if NCBI_SEMAPHORE_USE_NEW 1790unique_lock<mutex> lck(m_Mtx);
1791 while(!x_TryAcquire()) {
1795 #if defined(NCBI_POSIX_THREADS) 1798 "CSemaphore::Wait() - pthread_mutex_lock() failed");
1807 if(status != 0 && status != EINTR) {
1810 "CSemaphore::Wait() - pthread_cond_wait() and " 1811 "pthread_mutex_unlock() failed");
1813 "CSemaphore::Wait() - " 1814 "pthread_cond_wait() failed");
1823 "CSemaphore::Wait() - pthread_mutex_unlock() failed");
1825 #elif defined(NCBI_WIN32_THREADS) 1827 "CSemaphore::Wait() - WaitForSingleObject() failed");
1831 "CSemaphore::Wait() - " 1832 "wait with zero count in one-thread mode(?!)");
1838 #if defined(NCBI_NO_THREADS) 1839 # define NCBI_THREADS_ARG(arg) 1841 # define NCBI_THREADS_ARG(arg) arg 1847 #if NCBI_SEMAPHORE_USE_NEW 1848unique_lock<mutex> lck(m_Mtx);
1849 #if defined(NCBI_NO_THREADS) 1850 returnx_TryAcquire();
1852 if(x_TryAcquire()) {
1855 if(timeout_sec == 0 && timeout_nsec == 0) {
1856 returnx_TryAcquire();
1858chrono::time_point<chrono::steady_clock> to = chrono::steady_clock::now() + chrono::seconds(timeout_sec) + chrono::nanoseconds(timeout_nsec);
1859cv_status res = cv_status::no_timeout;
1860 while(!x_TryAcquire()) {
1861res = m_Cv.wait_until(lck, to);
1862 if(res == cv_status::timeout) {
1869 #if defined(NCBI_POSIX_THREADS) 1872 "CSemaphore::TryWait() - pthread_mutex_lock() failed");
1874 boolretval =
false;
1879 else if(timeout_sec > 0 || timeout_nsec > 0) {
1880 # ifdef NCBI_OS_SOLARIS 1883 if(timeout_sec >= 100 * 1000 * 1000) {
1884timeout_sec = 100 * 1000 * 1000;
1888 static const unsigned intkBillion = 1000 * 1000 * 1000;
1890 structtimespec timeout = { 0, 0 };
1893timeout.tv_sec = now.tv_sec;
1894timeout.tv_nsec = now.tv_usec * 1000 + timeout_nsec;
1895 if((
unsigned int)timeout.tv_nsec >= kBillion) {
1896timeout.tv_sec += timeout.tv_nsec / kBillion;
1897timeout.tv_nsec %= kBillion;
1899 if(timeout_sec > (
unsigned int)(
kMax_Int- timeout.tv_sec)) {
1902timeout.tv_nsec = kBillion - 1;
1904timeout.tv_sec += timeout_sec;
1911 if(status == ETIMEDOUT) {
1913}
else if(status != 0 && status != EINTR) {
1917 "CSemaphore::TryWait() - pthread_cond_timedwait() and " 1918 "pthread_mutex_unlock() failed");
1920 "pthread_cond_timedwait() failed");
1932 "CSemaphore::TryWait() - pthread_mutex_unlock() failed");
1936 #elif defined(NCBI_WIN32_THREADS) 1938 if(timeout_sec >= kMax_ULong / 1000) {
1939timeout_msec = kMax_ULong;
1941timeout_msec = timeout_sec * 1000 + timeout_nsec / (1000 * 1000);
1943 DWORDres = WaitForSingleObject(
m_Sem->sem, timeout_msec);
1945 "CSemaphore::TryWait() - WaitForSingleObject() failed");
1946 return(res == WAIT_OBJECT_0);
1976 #if NCBI_SEMAPHORE_USE_NEW 1977unique_lock<mutex> lck( m_Mtx);
1979 "CSemaphore::Post() - attempt to exceed max_count");
1983 #if defined (NCBI_POSIX_THREADS) 1986 "CSemaphore::Post() - pthread_mutex_lock() failed");
1992 "CSemaphore::Post() - attempt to exceed max_count and " 1993 "pthread_mutex_unlock() failed");
1995 "CSemaphore::Post() - attempt to exceed max_count");
2001err_code = pthread_cond_broadcast(&
m_Sem->
cond);
2005 for(
unsigned intn_sig = 0; n_sig <
count; n_sig++) {
2006err_code = pthread_cond_signal(&
m_Sem->
cond);
2007 if(err_code != 0) {
2008err_code = pthread_cond_broadcast(&
m_Sem->
cond);
2015 if(err_code == 0) {
2019 "CSemaphore::Post() - pthread_mutex_unlock() failed");
2026 "CSemaphore::Post() - pthread_cond_signal/broadcast() and " 2027 "pthread_mutex_unlock() failed");
2029 "CSemaphore::Post() - " 2030 "pthread_cond_signal/broadcast() failed");
2032 #elif defined(NCBI_WIN32_THREADS) 2035 "CSemaphore::Post() - ReleaseSemaphore() failed");
2039 "CSemaphore::Post() - attempt to exceed max_count");
2050 #if defined(NCBI_WIN32_THREADS) && defined(NCBI_FASTRWLOCK_USE_NEW) 2051AcquireSRWLockShared(&m_Lock);
2064 #if defined(NCBI_WIN32_THREADS) && defined(NCBI_FASTRWLOCK_USE_NEW) 2065ReleaseSRWLockShared(&m_Lock);
2074 #if defined(NCBI_WIN32_THREADS) && defined(NCBI_FASTRWLOCK_USE_NEW) 2075AcquireSRWLockExclusive(&m_Lock);
2088 #if defined(NCBI_WIN32_THREADS) && defined(NCBI_FASTRWLOCK_USE_NEW) 2089ReleaseSRWLockExclusive(&m_Lock);
2129lstn->OnLockAcquired(
this);
2146lstn->OnLockReleased(
this);
2190holder->
Init(lock, typ);
2209: m_Factory(factory)
2220 # define RWLockFatal Fatal 2222 # define RWLockFatal Critical 2229<<
"Destroying YieldingRWLock with unreleased locks");
2233<<
"Destroying YieldingRWLock with " 2234 "some locks waiting to acquire");
2243 intother_type = 1 - lock_type;
2257holder->m_LockAcquired =
true;
2260holder->x_OnLockAcquired();
2278 if(save_acquired) {
2288first_next->m_LockAcquired =
true;
2293 if(next_hldr->m_Type != next_type)
2296next_hldr->m_LockAcquired =
true;
2298next_holders.push_back(next_hldr);
2304THoldersList::iterator it
2312 if(save_acquired) {
2316first_next->x_OnLockAcquired();
2319(*it)->x_OnLockAcquired();
2365 #if defined(NCBI_THREADS) 2370 #if defined(NCBI_THREADS) 2371 #if defined(NCBI_OS_MSWIN) 2372InitializeConditionVariable(&m_ConditionVar);
2374 intres = pthread_cond_init(&m_ConditionVar,
NULL);
2380 "CConditionVariable: not enough resources");
2383 "CConditionVariable: not enough memory");
2386 "CConditionVariable: attempt to reinitialize" 2387 " already used variable");
2390 "CConditionVariable: invalid attribute value");
2393 "CConditionVariable: unknown error");
2402 #if defined(NCBI_THREADS) 2403 #if !defined(NCBI_OS_MSWIN) 2410 "~CConditionVariable: attempt to destroy variable that" 2411 " is currently in use");
2415 "~CConditionVariable: invalid condition variable");
2419 "~CConditionVariable: unknown error");
2421 NCBI_TROUBLE(
"CConditionVariable: pthread_cond_destroy() failed");
2427 #if defined(NCBI_THREADS) 2486 "WaitForSignal called with different mutexes");
2492(SSystemFastMutex& mutex,
const CDeadline& deadline)
2498 #if defined(NCBI_OS_MSWIN) 2501 #if defined(NCBI_FASTMUTEX_USE_NEW) 2502 BOOLres = SleepConditionVariableSRW(&
m_ConditionVar, &mutex.m_Handle, timeout_msec, 0);
2504 BOOLres = SleepConditionVariableCS(&
m_ConditionVar, &mutex.m_Handle, timeout_msec);
2511 DWORDerr_code = GetLastError();
2512 if(err_code == ERROR_TIMEOUT || err_code == WAIT_TIMEOUT)
2516 "WaitForSignal failed");
2528res = pthread_cond_timedwait(&
m_ConditionVar, &mutex.m_Handle, &ts);
2538 "WaitForSignal failed: invalid paramater");
2541 "WaitForSignal: mutex not owned by the current thread");
2544 "WaitForSignal failed: unknown error");
2557 #if defined(NCBI_THREADS) 2558SSystemMutex& sys_mtx = mutex;
2559 if(sys_mtx.m_Count != 1) {
2561 "WaitForSignal: mutex lock count not 1");
2563 #if defined(NCBI_OS_MSWIN) 2566 "WaitForSignal: mutex not owned by the current thread");
2569sys_mtx.Unlock(SSystemFastMutex::ePseudo);
2571sys_mtx.Lock(SSystemFastMutex::ePseudo);
2582 #if defined(NCBI_THREADS) 2583SSystemFastMutex& sys_mtx = mutex;
2584sys_mtx.
Unlock(SSystemFastMutex::ePseudo);
2586sys_mtx.Lock(SSystemFastMutex::ePseudo);
2596 #if defined(NCBI_THREADS) 2597 #if defined(NCBI_OS_MSWIN) 2605 "SignalSome failed: invalid paramater");
2608 "SignalSome failed: unknown error");
2618 #if defined(NCBI_THREADS) 2619 #if defined(NCBI_OS_MSWIN) 2627 "SignalAll failed: invalid paramater");
2630 "SignalAll failed: unknown error");
CConditionVariableException â.
Object factory for simple creation and deletion of the object with one parameter passed to object's c...
~CQuickAndDirtySamePointerGuard()
bool DetectedDifferentPointers(void)
volatile TPointer & m_GuardedPtr
CAtomicCounter & m_AtomicCounter
CQuickAndDirtySamePointerGuard(CAtomicCounter &atomic_counter, TPointer volatile &guarded_ptr, TPointer new_ptr)
Default implementation of IRWLockHolder_Factory.
THolderPool m_Pool
Implementation of CRWLockHolder objects pool.
CObjFactory_NewParam< CRWLockHolder, CRWLockHolder_Pool * > THolderPoolFactory
virtual ~CRWLockHolder_Pool(void)
CObjPool< CRWLockHolder, THolderPoolFactory > THolderPool
virtual void DeleteHolder(CRWLockHolder *holder)
Free unnecessary (and unreferenced by anybody) CRWLockHolder object.
virtual CRWLockHolder * CreateHolder(CYieldingRWLock *lock, ERWLockType typ)
Obtain new CRWLockHolder object for given CYieldingRWLock and necessary lock type.
Holder of the lock inside CYieldingRWLock.
CTimeout â Timeout interval.
Read/write lock without blocking calls.
Interface for factory creating CRWLockHolder objects.
static const char * expected[]
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
TValue Add(int delta) THROWS_NONE
Atomically add value (=delta), and return new counter value.
TValue Get(void) const THROWS_NONE
Get atomic counter value.
#define NCBI_TROUBLE(mess)
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
void Critical(CExceptionArgs_Base &args)
void Error(CExceptionArgs_Base &args)
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
TErrCode GetErrCode(void) const
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
static mode_t MakeModeT(TMode user_mode, TMode group_mode, TMode other_mode, TSpecialModeBits special)
Construct mode_t value from permission modes.
@ fWrite
Write permission.
bool NotNull(void) const THROWS_NONE
Check if pointer is not null â same effect as NotEmpty().
bool Referenced(void) const THROWS_NONE
Check if object is referenced.
void Return(TObjType *obj)
Return object to the pool for future use.
TObjType * Get(void)
Get object from the pool, create if necessary.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
#define NCBI_SCHED_YIELD()
volatile unsigned int m_WaitingWriters
Number of writers waiting; zero if not keeping track.
ERWLockType
Type of locking provided by CYieldingRWLock.
ELockSemantics
This is for condition variables.
unique_ptr< CInternalRWLock > m_RW
Platform-dependent RW-lock data.
struct SSemaphore * m_Sem
System-specific semaphore data.
bool TryLock(void)
Attempt to lock the mutex and return TRUE if it succeeded or FALSE if mutex is locked by other thread...
CSemaphore(unsigned int init_count, unsigned int max_count)
Constructor.
void Lock(void)
Acquire mutex for the current thread with no nesting checks.
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
void ReadUnlock(void)
Release read lock.
virtual ~CRWLockHolder(void)
~CConditionVariable(void)
void SignalSome(void)
Wake at least one of the threads that are currently waiting on this condition variable (if any thread...
ERWLockType m_Type
Type of lock held.
static bool IsSupported(void)
void Wait(void)
Wait on semaphore.
CFastMutex m_WriteLock
Mutex implementing write lock.
void ReadLock(void)
Read lock.
bool TryReadLock(void)
Try read lock.
void Reset(void)
Reset holder to be able to use it later (after calling Init() )
CSpinLock m_ObjLock
Main locking mutex for object operations.
TFlags m_Flags
Configuration flags.
void WriteUnlock(void)
Release write lock.
TRWLockHolderRef AcquireLock(ERWLockType lock_type)
General method to request read or write lock.
THoldersList m_LockWaits
Queue for waiting lock requests.
virtual CRWLockHolder * CreateHolder(CYieldingRWLock *lock, ERWLockType typ)=0
Obtain new CRWLockHolder object for given CYieldingRWLock and necessary lock type.
vector< TThreadSystemID > m_Readers
List of all readers or writers.
volatile long m_Count
Number of readers (if >0) or writers (if <0)
SSystemFastMutex *volatile m_WaitMutex
IRWLockHolder_Factory * m_Factory
Factory created the holder.
bool TryWriteLock(void)
Try write lock.
bool x_MayAcquireForReading(TThreadSystemID self_id)
bool x_WaitForSignal(SSystemFastMutex &mutex, const CDeadline &timeout)
virtual void DeleteThis(void)
"Delete" this holder after last reference was removed.
TListenersList m_Listeners
List of holder listeners.
IRWLockHolder_Factory * m_Factory
Factory creating CRWLockHolder objects.
void x_OnLockReleased(void)
Callback called at the moment when lock is released.
bool WaitForSignal(CMutex &mutex, const CDeadline &deadline=CDeadline::eInfinite)
Release mutex and lock the calling thread until the condition variable is signalled.
void SignalAll(void)
Wake all threads that are currently waiting on the condition variable.
pthread_mutex_t TSystemMutex
Define a platform independent system mutex.
CAtomicCounter_WithAutoInit m_WaitCounter
CRWLock(TFlags flags=0)
Constructor.
volatile TThreadSystemID m_Owner
Writer ID, one of the readers ID.
void Init(CYieldingRWLock *lock, ERWLockType typ)
Initialize holder for given CYieldingRWLock and necessary lock type.
void Unlock(void)
Unlock the mutex.
void ReadLock(void)
Acquire read lock.
void ReleaseLock(void)
Release the lock held or cancel request for the lock.
virtual void DeleteHolder(CRWLockHolder *holder)=0
Free unnecessary (and unreferenced by anybody) CRWLockHolder object.
CAtomicCounter m_LockCount
Number of read locks acquired or value of kWriteLockValue if write lock was acquired.
void x_ReleaseLock(CRWLockHolder *holder)
Main implementation releasing lock.
deque< TRWLockHolderRef > THoldersList
void Lock(void)
Lock the mutex.
list< TRWLockHolder_ListenerWeakRef > TListenersList
void x_OnLockAcquired(void)
Callback called at the moment when lock is granted.
void WriteLock(void)
Write lock.
int m_Locks[2]
Number of locks granted on this object by type.
CYieldingRWLock * m_Lock
Lock object the holder is assigned to.
void WriteLock(void)
Acquire write lock.
CONDITION_VARIABLE m_ConditionVar
pthread_t TThreadSystemID
Define platform-dependent thread ID type.
~CYieldingRWLock(void)
It is fatal error to destroy the object while some locks are pending.
bool TryWait(unsigned int timeout_sec=0, unsigned int timeout_nsec=0)
Timed wait.
virtual ~IRWLockHolder_Factory(void)
~CSemaphore(void)
Destructor.
void Post(unsigned int count=1)
Increment the semaphore by "count".
CSpinLock m_ObjLock
Mutex for operating listeners.
int TFlags
binary OR of EFlags
CYieldingRWLock(IRWLockHolder_Factory *factory=NULL)
Create read/write lock with custom holders factory.
~CRWLock(void)
Destructor.
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
void *volatile m_Value
Flag showing if mutex is locked (non-NULL value) or unlocked (NULL value).
void Unlock(void)
Release mutex with no owner or nesting checks.
bool m_LockAcquired
Flag if lock was acquired.
static TThreadSystemID GetCurrentThreadSystemID(void)
Get the current thread ID.
void Unlock(void)
Release the RW-lock.
virtual ~IRWLockHolder_Listener(void)
@ fFavorWriters
Forbid further readers from acquiring the lock if any writers are waiting for it, to keep would-be wr...
@ eMutexLockCount
Mutex passed to WaitForSignal is not owned by the current thread.
@ eMutexOwner
Different mutexes were supplied for concurrent WaitForSignal operations on this condition variable.
@ eMutexDifferent
Condition variable is not supported on this platform.
@ eInvalidValue
Parameter of WaitForSignal function is invalid.
@ fTrackReaders
Keep track of which threads have read locks.
@ kWriteLockValue
Number in lock count showing that write lock is acquired.
@ eUninitialized
Uninitialized error.
@ eTryLock
Attempted lock error.
@ eOwner
Not owned error.
CNanoTimeout GetRemainingTime(void) const
Get time left to the expiration.
void GetNano(unsigned int *sec, unsigned int *nanosec) const
Get timeout in seconds and nanoseconds.
unsigned long GetAsMilliSeconds(void) const
Get as number of milliseconds.
bool IsInfinite(void) const
Check if the deadline is infinite.
void GetExpirationTime(time_t *sec, unsigned int *nanosec) const
Get the number of seconds and nanoseconds (since 1/1/1970).
#define HANDLE
An abstraction for a file handle.
Definition of all error codes used in corelib (xncbi.lib).
int gettimeofday(struct timeval *tp, void *unused)
#define TRUE
bool replacment for C indicating true.
#define FALSE
bool replacment for C indicating false.
void * SwapPointers(void *volatile *location, void *new_value)
#define xncbi_ValidateAndErrnoReport(expression, message)
#define xncbi_VerifyAndErrorReport(expression)
#define xncbi_ValidatePthread(expression, expected_value, message)
#define xncbi_Validate(expression, message)
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
void interlocked_set(volatile long *val, long new_val)
#define WRITE_MUTEX_EVENT(mutex, message)
bool interlocked_dec_min(volatile long *val, long min)
bool interlocked_dec_max(volatile long *val, long max)
void s_ThrowIfDifferentMutexes(CQuickAndDirtySamePointerGuard< SSystemFastMutex > &mutex_guard)
#define NCBI_THREADS_ARG(arg)
bool interlocked_inc_max(volatile long *val, long max)
bool interlocked_inc_min(volatile long *val, long min)
static CSafeStatic< CRWLockHolder_Pool > s_RWHolderPool
Default CRWLockHolder pool used in CYieldingRWLock.
Multi-threading â mutexes; rw-locks; semaphore.
atomic< unsigned int > count
atomic< unsigned int > wait_count
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4