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 _AUTO_LOCKER_H 6 #define _AUTO_LOCKER_H 7 8 9 #include <stddef.h> 10 11 12 namespace BPrivate { 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 // AutoLockerHandlerLocking 30 template<typename Lockable> 31 class AutoLockerHandlerLocking { 32 public: 33 inline bool Lock(Lockable* lockable) 34 { 35 return lockable->LockLooper(); 36 } 37 38 inline void Unlock(Lockable* lockable) 39 { 40 lockable->UnlockLooper(); 41 } 42 }; 43 44 // AutoLockerReadLocking 45 template<typename Lockable> 46 class AutoLockerReadLocking { 47 public: 48 inline bool Lock(Lockable* lockable) 49 { 50 return lockable->ReadLock(); 51 } 52 53 inline void Unlock(Lockable* lockable) 54 { 55 lockable->ReadUnlock(); 56 } 57 }; 58 59 // AutoLockerWriteLocking 60 template<typename Lockable> 61 class AutoLockerWriteLocking { 62 public: 63 inline bool Lock(Lockable* lockable) 64 { 65 return lockable->WriteLock(); 66 } 67 68 inline void Unlock(Lockable* lockable) 69 { 70 lockable->WriteUnlock(); 71 } 72 }; 73 74 // AutoLocker 75 template<typename Lockable, 76 typename Locking = AutoLockerStandardLocking<Lockable> > 77 class AutoLocker { 78 private: 79 typedef AutoLocker<Lockable, Locking> ThisClass; 80 public: 81 inline AutoLocker() 82 : 83 fLockable(NULL), 84 fLocked(false) 85 { 86 } 87 88 inline AutoLocker(const Locking& locking) 89 : 90 fLockable(NULL), 91 fLocking(locking), 92 fLocked(false) 93 { 94 } 95 96 inline AutoLocker(Lockable* lockable, bool alreadyLocked = false, 97 bool lockIfNotLocked = true) 98 : 99 fLockable(lockable), 100 fLocked(fLockable && alreadyLocked) 101 { 102 if (!alreadyLocked && lockIfNotLocked) 103 Lock(); 104 } 105 106 inline AutoLocker(Lockable& lockable, bool alreadyLocked = false, 107 bool lockIfNotLocked = true) 108 : 109 fLockable(&lockable), 110 fLocked(fLockable && alreadyLocked) 111 { 112 if (!alreadyLocked && lockIfNotLocked) 113 Lock(); 114 } 115 116 inline ~AutoLocker() 117 { 118 Unlock(); 119 } 120 121 inline void SetTo(Lockable* lockable, bool alreadyLocked, 122 bool lockIfNotLocked = true) 123 { 124 Unlock(); 125 fLockable = lockable; 126 fLocked = (lockable && alreadyLocked); 127 if (!alreadyLocked && lockIfNotLocked) 128 Lock(); 129 } 130 131 inline void SetTo(Lockable& lockable, bool alreadyLocked, 132 bool lockIfNotLocked = true) 133 { 134 SetTo(&lockable, alreadyLocked, lockIfNotLocked); 135 } 136 137 inline void Unset() 138 { 139 Unlock(); 140 Detach(); 141 } 142 143 inline bool Lock() 144 { 145 if (fLockable && !fLocked) 146 fLocked = fLocking.Lock(fLockable); 147 return fLocked; 148 } 149 150 inline void Unlock() 151 { 152 if (fLockable && fLocked) { 153 fLocking.Unlock(fLockable); 154 fLocked = false; 155 } 156 } 157 158 inline Lockable* Get() 159 { 160 return fLockable; 161 } 162 163 inline Lockable* Detach() 164 { 165 Lockable* res = fLockable; 166 fLockable = NULL; 167 fLocked = false; 168 return res; 169 } 170 171 inline AutoLocker<Lockable, Locking>& operator=(Lockable* lockable) 172 { 173 SetTo(lockable); 174 return *this; 175 } 176 177 inline AutoLocker<Lockable, Locking>& operator=(Lockable& lockable) 178 { 179 SetTo(&lockable); 180 return *this; 181 } 182 183 inline bool IsLocked() const { return fLocked; } 184 185 inline operator bool() const { return fLocked; } 186 187 protected: 188 Lockable* fLockable; 189 Locking fLocking; 190 bool fLocked; 191 }; 192 193 194 } // namespace BPrivate 195 196 using ::BPrivate::AutoLocker; 197 using ::BPrivate::AutoLockerHandlerLocking; 198 using ::BPrivate::AutoLockerReadLocking; 199 using ::BPrivate::AutoLockerWriteLocking; 200 201 #endif // _AUTO_LOCKER_H 202