From 75648e80cfb13ee0589b246c4c0238b5e7c99abd Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 4 Mar 2018 11:31:21 +0100 Subject: [PATCH] Modified cStateLock's SetExplicitModify() and IncState() --- HISTORY | 4 +++- thread.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++--------- thread.h | 22 +++++++++++++++------ tools.c | 4 ++-- 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/HISTORY b/HISTORY index 7a0e034d..869fd049 100644 --- a/HISTORY +++ b/HISTORY @@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History a subdirectory. - SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details). -2018-03-03: Version 2.3.9 +2018-03-04: Version 2.3.9 - Updated the Italian OSD texts (thanks to Diego Pierotto). - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). @@ -9293,3 +9293,5 @@ Video Disk Recorder Revision History stuttering replay in fast forward and fast rewind mode in case the video directory is mounted via NFS. You can re-enable it by setting the macro USE_FADVISE_READ to 1 in tools.c. +- Modified cStateLock's SetExplicitModify() and IncState() (changed to SetModified()) to + allow for the introduction of syncing a separate cStateKey to a cStateLock. diff --git a/thread.c b/thread.c index 8fc23400..d2640378 100644 --- a/thread.c +++ b/thread.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 4.11 2017/06/25 12:08:16 kls Exp $ + * $Id: thread.c 4.12 2018/03/04 11:23:09 kls Exp $ */ #include "thread.h" @@ -716,7 +716,8 @@ cStateLock::cStateLock(const char *Name) name = Name; threadId = 0; state = 0; - explicitModify = false; + explicitModify = emDisabled; + syncStateKey = NULL; } bool cStateLock::Lock(cStateKey &StateKey, bool Write, int TimeoutMs) @@ -764,30 +765,70 @@ void cStateLock::Unlock(cStateKey &StateKey, bool IncState) return; } if (StateKey.write && threadId != cThread::ThreadId()) { - esyslog("ERROR: cStateLock::Unlock() called without holding a lock (tid=%d, lock=%s)", threadId, name); + esyslog("ERROR: cStateLock::Unlock() called without holding a write lock (tid=%d, lock=%s)", threadId, name); ABORT; return; } - if (StateKey.write && IncState && !explicitModify) + if (StateKey.write && (IncState && explicitModify != emArmed || explicitModify == emEnabled)) { + if (syncStateKey && syncStateKey->state == state) + syncStateKey->state++; state++; + } StateKey.state = state; if (StateKey.write) { StateKey.write = false; threadId = 0; - explicitModify = false; + explicitModify = emDisabled; + syncStateKey = NULL; } dbglockseq(name, false, false); rwLock.Unlock(); } -void cStateLock::IncState(void) +void cStateLock::SetSyncStateKey(cStateKey &StateKey) +{ + dbglocking("%5d %-12s %10p SetSyncStateKey\n", cThread::ThreadId(), name, &StateKey); + if (threadId != cThread::ThreadId()) { + esyslog("ERROR: cStateLock::SetSyncStateKey() called without holding a write lock (tid=%d, lock=%s)", threadId, name); + ABORT; + return; + } + if (StateKey.stateLock == this) { + esyslog("ERROR: cStateLock::SetSyncStateKey() called with locked key (tid=%d, lock=%s)", threadId, name); + ABORT; + return; + } + if (syncStateKey) { + esyslog("ERROR: cStateLock::SetSyncStateKey() called twice (tid=%d, lock=%s)", threadId, name); + ABORT; + return; + } + syncStateKey = &StateKey; +} + +void cStateLock::SetExplicitModify(void) { if (threadId != cThread::ThreadId()) { - esyslog("ERROR: cStateLock::IncState() called without holding a lock (tid=%d, lock=%s)", threadId, name); + esyslog("ERROR: cStateLock::SetExplicitModify() called without holding a write lock (tid=%d, lock=%s)", threadId, name); ABORT; + return; } - else - state++; + if (explicitModify != emDisabled) { + esyslog("ERROR: cStateLock::SetExplicitModify() called twice (tid=%d, lock=%s)", threadId, name); + ABORT; + return; + } + explicitModify = emArmed; +} + +void cStateLock::SetModified(void) +{ + if (threadId != cThread::ThreadId()) { + esyslog("ERROR: cStateLock::SetModified() called without holding a write lock (tid=%d, lock=%s)", threadId, name); + ABORT; + return; + } + explicitModify = emEnabled; } // --- cStateKey ------------------------------------------------------------- diff --git a/thread.h b/thread.h index fe8535b7..790c29a8 100644 --- a/thread.h +++ b/thread.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.h 4.3 2017/06/03 12:43:22 kls Exp $ + * $Id: thread.h 4.4 2018/03/04 11:27:55 kls Exp $ */ #ifndef __THREAD_H @@ -171,11 +171,13 @@ class cStateKey; class cStateLock { friend class cStateKey; private: + enum { emDisabled = 0, emArmed, emEnabled }; const char *name; tThreadId threadId; cRwLock rwLock; int state; - bool explicitModify; + int explicitModify; + cStateKey *syncStateKey; void Unlock(cStateKey &StateKey, bool IncState = true); ///< Releases a lock that has been obtained by a previous call to Lock() ///< with the given StateKey. If this was a write-lock, and IncState is true, @@ -211,13 +213,21 @@ public: ///< If Write is true (i.e. a write-lock is requested), the states of the ///< lock and the given StateKey don't matter, it will always try to obtain ///< a write lock. - void SetExplicitModify(void) { explicitModify = true; } + void SetSyncStateKey(cStateKey &StateKey); + ///< Sets the given StateKey to be synchronized to the state of this lock. + ///< The caller must currenty hold a write lock on this lock, with a cStateKey + ///< that is different from the given StateKey. If, when removing the key that + ///< is holding the write lock, the StateKey's current state is the same as that + ///< of the lock, it will be increased together with the lock's state. + void SetExplicitModify(void); ///< If you have obtained a write lock on this lock, and you don't want its ///< state to be automatically incremented when the lock is released, a call to - ///< this function will disable this, and you can explicitly call IncState() + ///< this function will disable this, and you can explicitly call SetModified() ///< to increment the state. - void IncState(void); - ///< Increments the state of this lock. + void SetModified(void); + ///< Sets this lock to have its state incremented when the current write lock + ///< state key is removed. Must have called SetExplicitModify() before calling + ///< this function. }; class cStateKey { diff --git a/tools.c b/tools.c index 4d3489af..7330fce1 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 4.10 2018/03/03 19:35:31 kls Exp $ + * $Id: tools.c 4.11 2018/03/04 10:28:04 kls Exp $ */ #include "tools.h" @@ -2253,7 +2253,7 @@ void cListBase::SetExplicitModify(void) void cListBase::SetModified(void) { - stateLock.IncState(); + stateLock.SetModified(); } const cListObject *cListBase::Get(int Index) const