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 12 namespace FSShell { 13 14 // AutoLockerStandardLocking 15 template<typename Lockable> 16 class AutoLockerStandardLocking { 17 public: 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 30 template<typename Lockable> 31 class AutoLockerReadLocking { 32 public: 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 45 template<typename Lockable> 46 class AutoLockerWriteLocking { 47 public: 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 60 template<typename Lockable, 61 typename Locking = AutoLockerStandardLocking<Lockable> > 62 class AutoLocker { 63 private: 64 typedef AutoLocker<Lockable, Locking> ThisClass; 65 public: 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 154 private: 155 Lockable *fLockable; 156 bool fLocked; 157 Locking fLocking; 158 }; 159 160 161 } // namespace FSShell 162 163 using FSShell::AutoLocker; 164 165 #endif // _FSSH_AUTO_LOCKER_H 166