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