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 12namespace BPrivate { 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// AutoLockerHandlerLocking 30template<typename Lockable> 31class AutoLockerHandlerLocking { 32public: 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 45template<typename Lockable> 46class AutoLockerReadLocking { 47public: 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 60template<typename Lockable> 61class AutoLockerWriteLocking { 62public: 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 75template<typename Lockable, 76 typename Locking = AutoLockerStandardLocking<Lockable> > 77class AutoLocker { 78private: 79 typedef AutoLocker<Lockable, Locking> ThisClass; 80public: 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 187protected: 188 Lockable* fLockable; 189 Locking fLocking; 190 bool fLocked; 191}; 192 193 194} // namespace BPrivate 195 196using ::BPrivate::AutoLocker; 197using ::BPrivate::AutoLockerHandlerLocking; 198using ::BPrivate::AutoLockerReadLocking; 199using ::BPrivate::AutoLockerWriteLocking; 200 201#endif // _AUTO_LOCKER_H 202