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