1a38a92c9SIngo Weinhold /* 2a38a92c9SIngo Weinhold * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net. 3a38a92c9SIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License. 4a38a92c9SIngo Weinhold */ 5a38a92c9SIngo Weinhold #ifndef _FSSH_AUTO_LOCKER_H 6a38a92c9SIngo Weinhold #define _FSSH_AUTO_LOCKER_H 7a38a92c9SIngo Weinhold 8a38a92c9SIngo Weinhold 9*e2dfe004SAxel Dörfler #include <fssh_types.h> 10e0fc5e73SAxel Dörfler 11e0fc5e73SAxel Dörfler 12a38a92c9SIngo Weinhold namespace FSShell { 13a38a92c9SIngo Weinhold 14a38a92c9SIngo Weinhold // AutoLockerStandardLocking 15a38a92c9SIngo Weinhold template<typename Lockable> 16a38a92c9SIngo Weinhold class AutoLockerStandardLocking { 17a38a92c9SIngo Weinhold public: Lock(Lockable * lockable)18a38a92c9SIngo Weinhold inline bool Lock(Lockable *lockable) 19a38a92c9SIngo Weinhold { 20a38a92c9SIngo Weinhold return lockable->Lock(); 21a38a92c9SIngo Weinhold } 22a38a92c9SIngo Weinhold Unlock(Lockable * lockable)23a38a92c9SIngo Weinhold inline void Unlock(Lockable *lockable) 24a38a92c9SIngo Weinhold { 25a38a92c9SIngo Weinhold lockable->Unlock(); 26a38a92c9SIngo Weinhold } 27a38a92c9SIngo Weinhold }; 28a38a92c9SIngo Weinhold 29a38a92c9SIngo Weinhold // AutoLockerReadLocking 30a38a92c9SIngo Weinhold template<typename Lockable> 31a38a92c9SIngo Weinhold class AutoLockerReadLocking { 32a38a92c9SIngo Weinhold public: Lock(Lockable * lockable)33a38a92c9SIngo Weinhold inline bool Lock(Lockable *lockable) 34a38a92c9SIngo Weinhold { 35a38a92c9SIngo Weinhold return lockable->ReadLock(); 36a38a92c9SIngo Weinhold } 37a38a92c9SIngo Weinhold Unlock(Lockable * lockable)38a38a92c9SIngo Weinhold inline void Unlock(Lockable *lockable) 39a38a92c9SIngo Weinhold { 40a38a92c9SIngo Weinhold lockable->ReadUnlock(); 41a38a92c9SIngo Weinhold } 42a38a92c9SIngo Weinhold }; 43a38a92c9SIngo Weinhold 44a38a92c9SIngo Weinhold // AutoLockerWriteLocking 45a38a92c9SIngo Weinhold template<typename Lockable> 46a38a92c9SIngo Weinhold class AutoLockerWriteLocking { 47a38a92c9SIngo Weinhold public: Lock(Lockable * lockable)48a38a92c9SIngo Weinhold inline bool Lock(Lockable *lockable) 49a38a92c9SIngo Weinhold { 50a38a92c9SIngo Weinhold return lockable->WriteLock(); 51a38a92c9SIngo Weinhold } 52a38a92c9SIngo Weinhold Unlock(Lockable * lockable)53a38a92c9SIngo Weinhold inline void Unlock(Lockable *lockable) 54a38a92c9SIngo Weinhold { 55a38a92c9SIngo Weinhold lockable->WriteUnlock(); 56a38a92c9SIngo Weinhold } 57a38a92c9SIngo Weinhold }; 58a38a92c9SIngo Weinhold 59a38a92c9SIngo Weinhold // AutoLocker 60a38a92c9SIngo Weinhold template<typename Lockable, 61a38a92c9SIngo Weinhold typename Locking = AutoLockerStandardLocking<Lockable> > 62a38a92c9SIngo Weinhold class AutoLocker { 63a38a92c9SIngo Weinhold private: 64a38a92c9SIngo Weinhold typedef AutoLocker<Lockable, Locking> ThisClass; 65a38a92c9SIngo Weinhold public: AutoLocker()66a38a92c9SIngo Weinhold inline AutoLocker() 67a38a92c9SIngo Weinhold : fLockable(NULL), 68a38a92c9SIngo Weinhold fLocked(false) 69a38a92c9SIngo Weinhold { 70a38a92c9SIngo Weinhold } 71a38a92c9SIngo Weinhold 72a38a92c9SIngo Weinhold inline AutoLocker(Lockable *lockable, bool alreadyLocked = false, 73a38a92c9SIngo Weinhold bool lockIfNotLocked = true) fLockable(lockable)74a38a92c9SIngo Weinhold : fLockable(lockable), 75a38a92c9SIngo Weinhold fLocked(fLockable && alreadyLocked) 76a38a92c9SIngo Weinhold { 77a38a92c9SIngo Weinhold if (!alreadyLocked && lockIfNotLocked) 78a38a92c9SIngo Weinhold Lock(); 79a38a92c9SIngo Weinhold } 80a38a92c9SIngo Weinhold 81a38a92c9SIngo Weinhold inline AutoLocker(Lockable &lockable, bool alreadyLocked = false, 82a38a92c9SIngo Weinhold bool lockIfNotLocked = true) 83a38a92c9SIngo Weinhold : fLockable(&lockable), 84a38a92c9SIngo Weinhold fLocked(fLockable && alreadyLocked) 85a38a92c9SIngo Weinhold { 86a38a92c9SIngo Weinhold if (!alreadyLocked && lockIfNotLocked) 87a38a92c9SIngo Weinhold Lock(); 88a38a92c9SIngo Weinhold } 89a38a92c9SIngo Weinhold ~AutoLocker()90a38a92c9SIngo Weinhold inline ~AutoLocker() 91a38a92c9SIngo Weinhold { 92a38a92c9SIngo Weinhold Unlock(); 93a38a92c9SIngo Weinhold } 94a38a92c9SIngo Weinhold 95a38a92c9SIngo Weinhold inline void SetTo(Lockable *lockable, bool alreadyLocked, 96a38a92c9SIngo Weinhold bool lockIfNotLocked = true) 97a38a92c9SIngo Weinhold { 98a38a92c9SIngo Weinhold Unlock(); 99a38a92c9SIngo Weinhold fLockable = lockable; 100a38a92c9SIngo Weinhold fLocked = alreadyLocked; 101a38a92c9SIngo Weinhold if (!alreadyLocked && lockIfNotLocked) 102a38a92c9SIngo Weinhold Lock(); 103a38a92c9SIngo Weinhold } 104a38a92c9SIngo Weinhold 105a38a92c9SIngo Weinhold inline void SetTo(Lockable &lockable, bool alreadyLocked, 106a38a92c9SIngo Weinhold bool lockIfNotLocked = true) 107a38a92c9SIngo Weinhold { 108a38a92c9SIngo Weinhold SetTo(&lockable, alreadyLocked, lockIfNotLocked); 109a38a92c9SIngo Weinhold } 110a38a92c9SIngo Weinhold Unset()111a38a92c9SIngo Weinhold inline void Unset() 112a38a92c9SIngo Weinhold { 113a38a92c9SIngo Weinhold Unlock(); 114a38a92c9SIngo Weinhold Detach(); 115a38a92c9SIngo Weinhold } 116a38a92c9SIngo Weinhold Lock()117a38a92c9SIngo Weinhold inline bool Lock() 118a38a92c9SIngo Weinhold { 119a38a92c9SIngo Weinhold if (fLockable && !fLocked) 120a38a92c9SIngo Weinhold fLocked = fLocking.Lock(fLockable); 121a38a92c9SIngo Weinhold return fLocked; 122a38a92c9SIngo Weinhold } 123a38a92c9SIngo Weinhold Unlock()124a38a92c9SIngo Weinhold inline void Unlock() 125a38a92c9SIngo Weinhold { 126a38a92c9SIngo Weinhold if (fLockable && fLocked) { 127a38a92c9SIngo Weinhold fLocking.Unlock(fLockable); 128a38a92c9SIngo Weinhold fLocked = false; 129a38a92c9SIngo Weinhold } 130a38a92c9SIngo Weinhold } 131a38a92c9SIngo Weinhold Detach()132a38a92c9SIngo Weinhold inline void Detach() 133a38a92c9SIngo Weinhold { 134a38a92c9SIngo Weinhold fLockable = NULL; 135a38a92c9SIngo Weinhold fLocked = false; 136a38a92c9SIngo Weinhold } 137a38a92c9SIngo Weinhold 138a38a92c9SIngo Weinhold inline AutoLocker<Lockable, Locking> &operator=(Lockable *lockable) 139a38a92c9SIngo Weinhold { 140a38a92c9SIngo Weinhold SetTo(lockable); 141a38a92c9SIngo Weinhold return *this; 142a38a92c9SIngo Weinhold } 143a38a92c9SIngo Weinhold 144a38a92c9SIngo Weinhold inline AutoLocker<Lockable, Locking> &operator=(Lockable &lockable) 145a38a92c9SIngo Weinhold { 146a38a92c9SIngo Weinhold SetTo(&lockable); 147a38a92c9SIngo Weinhold return *this; 148a38a92c9SIngo Weinhold } 149a38a92c9SIngo Weinhold IsLocked()150a38a92c9SIngo Weinhold inline bool IsLocked() const { return fLocked; } 151a38a92c9SIngo Weinhold 152a38a92c9SIngo Weinhold inline operator bool() const { return fLocked; } 153a38a92c9SIngo Weinhold 154a38a92c9SIngo Weinhold private: 155a38a92c9SIngo Weinhold Lockable *fLockable; 156a38a92c9SIngo Weinhold bool fLocked; 157a38a92c9SIngo Weinhold Locking fLocking; 158a38a92c9SIngo Weinhold }; 159a38a92c9SIngo Weinhold 160a38a92c9SIngo Weinhold 161a38a92c9SIngo Weinhold } // namespace FSShell 162a38a92c9SIngo Weinhold 163a38a92c9SIngo Weinhold using FSShell::AutoLocker; 164a38a92c9SIngo Weinhold 165a38a92c9SIngo Weinhold #endif // _FSSH_AUTO_LOCKER_H 166