diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2015-09-01 11:14:27 +0200 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2015-09-01 11:14:27 +0200 |
commit | 3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d (patch) | |
tree | da57ce74189de9bfb27e1a747063c37cd62de501 /thread.h | |
parent | 8a7bc6a0bbf60cae8b6391a630880aad5cba3363 (diff) | |
download | vdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.gz vdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.bz2 |
Implemented strict locking of global lists
Diffstat (limited to 'thread.h')
-rw-r--r-- | thread.h | 90 |
1 files changed, 89 insertions, 1 deletions
@@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.h 3.2 2015/01/14 11:39:55 kls Exp $ + * $Id: thread.h 4.1 2015/08/17 13:06:24 kls Exp $ */ #ifndef __THREAD_H @@ -164,6 +164,94 @@ public: #define LOCK_THREAD cThreadLock ThreadLock(this) +class cStateKey; + +class cStateLock { + friend class cStateKey; +private: + const char *name; + tThreadId threadId; + cRwLock rwLock; + int state; + bool explicitModify; + 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, + ///< the state of the lock will be incremented. In any case, the (new) state + ///< of the lock will be copied to the StateKey's state. +public: + cStateLock(const char *Name = NULL); + bool Lock(cStateKey &StateKey, bool Write = false, int TimeoutMs = 0); + ///< Tries to get a lock and returns true if successful. + ///< If TimoutMs is not 0, it waits for the given number of milliseconds + ///< and returns false if no lock has been obtained within that time. + ///< Otherwise it waits indefinitely for the lock. The given StateKey + ///< will store which lock it has been used with, and will use that + ///< information when its Remove() function is called. + ///< There are two possible locks, one only for read access, and one + ///< for reading and writing: + ///< + ///< If Write is false (i.e. a read-lock is requested), the lock's state + ///< is compared to the given StateKey's state, and true is returned if + ///< they differ. + ///< If true is returned, the read-lock is still in place and the + ///< protected data structures can be safely accessed (in read-only mode!). + ///< Once the necessary operations have been performed, the lock must + ///< be released by a call to the StateKey's Remove() function. + ///< If false is returned, the state has not changed since the last check, + ///< and the read-lock has been released. In that case the protected + ///< data structures have not changed since the last call, so no action + ///< is required. Note that if TimeoutMs is used with read-locks, Lock() + ///< might return false even if the states of lock and key differ, just + ///< because it was unable to obtain the lock within the given time. + ///< You can call cStateKey::TimedOut() to detect this. + ///< + ///< 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; } + ///< 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() + ///< to increment the state. + void IncState(void); + ///< Increments the state of this lock. + }; + +class cStateKey { + friend class cStateLock; +private: + cStateLock *stateLock; + bool write; + int state; + bool timedOut; +public: + cStateKey(bool IgnoreFirst = false); + ///< Sets up a new state key. If IgnoreFirst is true, the first use + ///< of this key with a lock will not return true if the lock's state + ///< hasn't explicitly changed. + ~cStateKey(); + void Reset(void); + ///< Resets the state of this key, so that the next call to a lock's + ///< Lock() function with this key will return true, even if the + ///< lock's state hasn't changed. + void Remove(bool IncState = true); + ///< Removes this key from the lock it was previously used with. + ///< If this key was used to obtain a write lock, the state of the lock will + ///< be incremented and copied to this key. You can set IncState to false + ///< to prevent this. + bool StateChanged(void); + ///< Returns true if this key is used for obtaining a write lock, and the + ///< lock's state differs from that of the key. When used with a read lock, + ///< it always returns true, because otherwise the lock wouldn't have been + ///< obtained in the first place. + bool InLock(void) { return stateLock; } + ///< Returns true if this key is currently in a lock. + bool TimedOut(void) const { return timedOut; } + ///< Returns true if the last lock attempt this key was used with failed due + ///< to a timeout. + }; + class cIoThrottle { private: static cMutex mutex; |