1 /* 2 * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #ifndef KERNEL_UTIL_AUTO_LOCKER_H 7 #define KERNEL_UTIL_AUTO_LOCKER_H 8 9 #include <lock.h> 10 11 namespace BPrivate { 12 13 // AutoLockerStandardLocking 14 template<typename Lockable> 15 class AutoLockerStandardLocking { 16 public: 17 inline bool Lock(Lockable *lockable) 18 { 19 return lockable->Lock(); 20 } 21 22 inline void Unlock(Lockable *lockable) 23 { 24 lockable->Unlock(); 25 } 26 }; 27 28 // AutoLockerReadLocking 29 template<typename Lockable> 30 class AutoLockerReadLocking { 31 public: 32 inline bool Lock(Lockable *lockable) 33 { 34 return lockable->ReadLock(); 35 } 36 37 inline void Unlock(Lockable *lockable) 38 { 39 lockable->ReadUnlock(); 40 } 41 }; 42 43 // AutoLockerWriteLocking 44 template<typename Lockable> 45 class AutoLockerWriteLocking { 46 public: 47 inline bool Lock(Lockable *lockable) 48 { 49 return lockable->WriteLock(); 50 } 51 52 inline void Unlock(Lockable *lockable) 53 { 54 lockable->WriteUnlock(); 55 } 56 }; 57 58 // AutoLocker 59 template<typename Lockable, 60 typename Locking = AutoLockerStandardLocking<Lockable> > 61 class AutoLocker { 62 private: 63 typedef AutoLocker<Lockable, Locking> ThisClass; 64 public: 65 inline AutoLocker() 66 : fLockable(NULL), 67 fLocked(false) 68 { 69 } 70 71 inline AutoLocker(Lockable *lockable, bool alreadyLocked = false) 72 : fLockable(lockable), 73 fLocked(fLockable && alreadyLocked) 74 { 75 if (!fLocked) 76 _Lock(); 77 } 78 79 inline AutoLocker(Lockable &lockable, bool alreadyLocked = false) 80 : fLockable(&lockable), 81 fLocked(fLockable && alreadyLocked) 82 { 83 if (!fLocked) 84 _Lock(); 85 } 86 87 inline ~AutoLocker() 88 { 89 _Unlock(); 90 } 91 92 inline void SetTo(Lockable *lockable, bool alreadyLocked) 93 { 94 _Unlock(); 95 fLockable = lockable; 96 fLocked = alreadyLocked; 97 if (!fLocked) 98 _Lock(); 99 } 100 101 inline void SetTo(Lockable &lockable, bool alreadyLocked) 102 { 103 SetTo(&lockable, alreadyLocked); 104 } 105 106 inline void Unset() 107 { 108 _Unlock(); 109 } 110 111 inline void Unlock() 112 { 113 _Unlock(); 114 } 115 116 inline void Detach() 117 { 118 fLockable = NULL; 119 fLocked = false; 120 } 121 122 inline AutoLocker<Lockable, Locking> &operator=(Lockable *lockable) 123 { 124 SetTo(lockable); 125 return *this; 126 } 127 128 inline AutoLocker<Lockable, Locking> &operator=(Lockable &lockable) 129 { 130 SetTo(&lockable); 131 return *this; 132 } 133 134 inline bool IsLocked() const { return fLocked; } 135 136 inline operator bool() const { return fLocked; } 137 138 private: 139 inline void _Lock() 140 { 141 if (fLockable) 142 fLocked = fLocking.Lock(fLockable); 143 } 144 145 inline void _Unlock() 146 { 147 if (fLockable && fLocked) { 148 fLocking.Unlock(fLockable); 149 fLocked = false; 150 } 151 } 152 153 private: 154 Lockable *fLockable; 155 bool fLocked; 156 Locking fLocking; 157 }; 158 159 160 // #pragma mark - 161 // #pragma mark ----- instantiations ----- 162 163 // MutexLocking 164 class MutexLocking { 165 public: 166 inline bool Lock(mutex *lockable) 167 { 168 mutex_lock(lockable); 169 return true; 170 } 171 172 inline void Unlock(mutex *lockable) 173 { 174 mutex_unlock(lockable); 175 } 176 }; 177 178 // MutexLocker 179 typedef AutoLocker<mutex, MutexLocking> MutexLocker; 180 181 // RecursiveLockLocking 182 class RecursiveLockLocking { 183 public: 184 inline bool Lock(recursive_lock *lockable) 185 { 186 recursive_lock_lock(lockable); 187 return true; 188 } 189 190 inline void Unlock(recursive_lock *lockable) 191 { 192 recursive_lock_unlock(lockable); 193 } 194 }; 195 196 // RecursiveLocker 197 typedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker; 198 199 // BenaphoreLocking 200 class BenaphoreLocking { 201 public: 202 inline bool Lock(benaphore *lockable) 203 { 204 return benaphore_lock(lockable) == B_OK; 205 } 206 207 inline void Unlock(benaphore *lockable) 208 { 209 benaphore_unlock(lockable); 210 } 211 }; 212 213 // BenaphoreLocker 214 typedef AutoLocker<benaphore, BenaphoreLocking> BenaphoreLocker; 215 216 } // namespace BPrivate 217 218 using BPrivate::AutoLocker; 219 using BPrivate::MutexLocker; 220 using BPrivate::RecursiveLocker; 221 using BPrivate::BenaphoreLocker; 222 223 #endif // KERNEL_UTIL_AUTO_LOCKER_H 224