diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2016-12-08 10:18:32 +0100 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2016-12-08 10:18:32 +0100 |
commit | 85ae27e372fa1c433bd01809848cbba46e6706a6 (patch) | |
tree | dd41eaeb12f5ef81f8798593fbd6ee5514209408 /thread.c | |
parent | ce6c90a4506a80bf7e8fa55d2ab643478e97183f (diff) | |
download | vdr-85ae27e372fa1c433bd01809848cbba46e6706a6.tar.gz vdr-85ae27e372fa1c433bd01809848cbba46e6706a6.tar.bz2 |
The cRwLock class now allows nested read locks within a write lock from the same thread
Diffstat (limited to 'thread.c')
-rw-r--r-- | thread.c | 32 |
1 files changed, 25 insertions, 7 deletions
@@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 4.1 2015/08/29 14:43:03 kls Exp $ + * $Id: thread.c 4.2 2016/12/08 10:18:32 kls Exp $ */ #include "thread.h" @@ -151,6 +151,8 @@ void cCondVar::Broadcast(void) cRwLock::cRwLock(bool PreferWriter) { + locked = 0; + writeLockThreadId = 0; pthread_rwlockattr_t attr; pthread_rwlockattr_init(&attr); pthread_rwlockattr_setkind_np(&attr, PreferWriter ? PTHREAD_RWLOCK_PREFER_WRITER_NP : PTHREAD_RWLOCK_PREFER_READER_NP); @@ -170,8 +172,15 @@ bool cRwLock::Lock(bool Write, int TimeoutMs) if (!GetAbsTime(&abstime, TimeoutMs)) TimeoutMs = 0; } - if (Write) + if (Write) { Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock); + if (Result == 0) + writeLockThreadId = cThread::ThreadId(); + } + else if (writeLockThreadId == cThread::ThreadId()) { + locked++; // there can be any number of stacked read locks, so we keep track here + Result = 0; // aquiring a read lock while holding a write lock within the same thread is OK + } else Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock); return Result == 0; @@ -179,6 +188,13 @@ bool cRwLock::Lock(bool Write, int TimeoutMs) void cRwLock::Unlock(void) { + if (writeLockThreadId == cThread::ThreadId()) { // this is the thread that obtained the initial write lock + if (locked) { // this is the unlock of a read lock within the write lock + locked--; + return; + } + } + writeLockThreadId = 0; pthread_rwlock_unlock(&rwlock); } @@ -206,8 +222,8 @@ void cMutex::Lock(void) void cMutex::Unlock(void) { - if (!--locked) - pthread_mutex_unlock(&mutex); + if (!--locked) + pthread_mutex_unlock(&mutex); } // --- cThread --------------------------------------------------------------- @@ -474,9 +490,11 @@ void cStateLock::Unlock(cStateKey &StateKey, bool IncState) if (StateKey.write && IncState && !explicitModify) state++; StateKey.state = state; - StateKey.write = false; - threadId = 0; - explicitModify = false; + if (StateKey.write) { + StateKey.write = false; + threadId = 0; + explicitModify = false; + } rwLock.Unlock(); } |