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 // 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 : 68 fLockable(NULL), 69 fLocked(false) 70 { 71 } 72 73 inline AutoLocker(const Locking& locking) 74 : 75 fLockable(NULL), 76 fLocking(locking), 77 fLocked(false) 78 { 79 } 80 81 inline AutoLocker(Lockable* lockable, bool alreadyLocked = false, 82 bool lockIfNotLocked = true) 83 : 84 fLockable(lockable), 85 fLocked(fLockable && alreadyLocked) 86 { 87 if (!alreadyLocked && lockIfNotLocked) 88 Lock(); 89 } 90 91 inline AutoLocker(Lockable& lockable, bool alreadyLocked = false, 92 bool lockIfNotLocked = true) 93 : 94 fLockable(&lockable), 95 fLocked(fLockable && alreadyLocked) 96 { 97 if (!alreadyLocked && lockIfNotLocked) 98 Lock(); 99 } 100 101 inline ~AutoLocker() 102 { 103 Unlock(); 104 } 105 106 inline void SetTo(Lockable* lockable, bool alreadyLocked, 107 bool lockIfNotLocked = true) 108 { 109 Unlock(); 110 fLockable = lockable; 111 fLocked = (lockable && alreadyLocked); 112 if (!alreadyLocked && lockIfNotLocked) 113 Lock(); 114 } 115 116 inline void SetTo(Lockable& lockable, bool alreadyLocked, 117 bool lockIfNotLocked = true) 118 { 119 SetTo(&lockable, alreadyLocked, lockIfNotLocked); 120 } 121 122 inline void Unset() 123 { 124 Unlock(); 125 Detach(); 126 } 127 128 inline bool Lock() 129 { 130 if (fLockable && !fLocked) 131 fLocked = fLocking.Lock(fLockable); 132 return fLocked; 133 } 134 135 inline void Unlock() 136 { 137 if (fLockable && fLocked) { 138 fLocking.Unlock(fLockable); 139 fLocked = false; 140 } 141 } 142 143 inline void Detach() 144 { 145 fLockable = NULL; 146 fLocked = false; 147 } 148 149 inline AutoLocker<Lockable, Locking>& operator=(Lockable* lockable) 150 { 151 SetTo(lockable); 152 return *this; 153 } 154 155 inline AutoLocker<Lockable, Locking>& operator=(Lockable& lockable) 156 { 157 SetTo(&lockable); 158 return *this; 159 } 160 161 inline bool IsLocked() const { return fLocked; } 162 163 inline operator bool() const { return fLocked; } 164 165 protected: 166 Lockable* fLockable; 167 Locking fLocking; 168 bool fLocked; 169 }; 170 171 172 } // namespace BPrivate 173 174 using ::BPrivate::AutoLocker; 175 using ::BPrivate::AutoLockerReadLocking; 176 using ::BPrivate::AutoLockerWriteLocking; 177 178 #endif // _AUTO_LOCKER_H 179