Modified cStateLock's SetExplicitModify() and IncState()

This commit is contained in:
Klaus Schmidinger 2018-03-04 11:31:21 +01:00
parent 8a7540321d
commit 75648e80cf
4 changed files with 71 additions and 18 deletions

View File

@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History
a subdirectory. a subdirectory.
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details). - 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 Italian OSD texts (thanks to Diego Pierotto).
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - 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 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 is mounted via NFS. You can re-enable it by setting the macro USE_FADVISE_READ to 1
in tools.c. 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.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "thread.h"
@ -716,7 +716,8 @@ cStateLock::cStateLock(const char *Name)
name = Name; name = Name;
threadId = 0; threadId = 0;
state = 0; state = 0;
explicitModify = false; explicitModify = emDisabled;
syncStateKey = NULL;
} }
bool cStateLock::Lock(cStateKey &StateKey, bool Write, int TimeoutMs) bool cStateLock::Lock(cStateKey &StateKey, bool Write, int TimeoutMs)
@ -764,30 +765,70 @@ void cStateLock::Unlock(cStateKey &StateKey, bool IncState)
return; return;
} }
if (StateKey.write && threadId != cThread::ThreadId()) { 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; ABORT;
return; return;
} }
if (StateKey.write && IncState && !explicitModify) if (StateKey.write && (IncState && explicitModify != emArmed || explicitModify == emEnabled)) {
if (syncStateKey && syncStateKey->state == state)
syncStateKey->state++;
state++; state++;
}
StateKey.state = state; StateKey.state = state;
if (StateKey.write) { if (StateKey.write) {
StateKey.write = false; StateKey.write = false;
threadId = 0; threadId = 0;
explicitModify = false; explicitModify = emDisabled;
syncStateKey = NULL;
} }
dbglockseq(name, false, false); dbglockseq(name, false, false);
rwLock.Unlock(); 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()) { 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; ABORT;
return;
} }
else if (explicitModify != emDisabled) {
state++; 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 ------------------------------------------------------------- // --- cStateKey -------------------------------------------------------------

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __THREAD_H
@ -171,11 +171,13 @@ class cStateKey;
class cStateLock { class cStateLock {
friend class cStateKey; friend class cStateKey;
private: private:
enum { emDisabled = 0, emArmed, emEnabled };
const char *name; const char *name;
tThreadId threadId; tThreadId threadId;
cRwLock rwLock; cRwLock rwLock;
int state; int state;
bool explicitModify; int explicitModify;
cStateKey *syncStateKey;
void Unlock(cStateKey &StateKey, bool IncState = true); void Unlock(cStateKey &StateKey, bool IncState = true);
///< Releases a lock that has been obtained by a previous call to Lock() ///< 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, ///< 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 ///< 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 ///< lock and the given StateKey don't matter, it will always try to obtain
///< a write lock. ///< 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 ///< 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 ///< 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. ///< to increment the state.
void IncState(void); void SetModified(void);
///< Increments the state of this lock. ///< 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 { class cStateKey {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "tools.h"
@ -2253,7 +2253,7 @@ void cListBase::SetExplicitModify(void)
void cListBase::SetModified(void) void cListBase::SetModified(void)
{ {
stateLock.IncState(); stateLock.SetModified();
} }
const cListObject *cListBase::Get(int Index) const const cListObject *cListBase::Get(int Index) const