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(Lockable *lockable, bool alreadyLocked = false) 66 : fLockable(lockable), 67 fLocked(fLockable && alreadyLocked) 68 { 69 if (!fLocked) 70 _Lock(); 71 } 72 73 inline AutoLocker(Lockable &lockable, bool alreadyLocked = false) 74 : fLockable(&lockable), 75 fLocked(fLockable && alreadyLocked) 76 { 77 if (!fLocked) 78 _Lock(); 79 } 80 81 inline ~AutoLocker() 82 { 83 _Unlock(); 84 } 85 86 inline void SetTo(Lockable *lockable, bool alreadyLocked) 87 { 88 _Unlock(); 89 fLockable = lockable; 90 fLocked = alreadyLocked; 91 if (!fLocked) 92 _Lock(); 93 } 94 95 inline void SetTo(Lockable &lockable, bool alreadyLocked) 96 { 97 SetTo(&lockable, alreadyLocked); 98 } 99 100 inline void Unset() 101 { 102 _Unlock(); 103 } 104 105 inline void Unlock() 106 { 107 _Unlock(); 108 } 109 110 inline void Detach() 111 { 112 fLockable = NULL; 113 fLocked = false; 114 } 115 116 inline AutoLocker<Lockable, Locking> &operator=(Lockable *lockable) 117 { 118 SetTo(lockable); 119 return *this; 120 } 121 122 inline AutoLocker<Lockable, Locking> &operator=(Lockable &lockable) 123 { 124 SetTo(&lockable); 125 return *this; 126 } 127 128 inline bool IsLocked() const { return fLocked; } 129 130 inline operator bool() const { return fLocked; } 131 132 private: 133 inline void _Lock() 134 { 135 if (fLockable) 136 fLocked = fLocking.Lock(fLockable); 137 } 138 139 inline void _Unlock() 140 { 141 if (fLockable && fLocked) { 142 fLocking.Unlock(fLockable); 143 fLocked = false; 144 } 145 } 146 147 private: 148 Lockable *fLockable; 149 bool fLocked; 150 Locking fLocking; 151 }; 152 153 154 // #pragma mark - 155 // #pragma mark ----- instantiations ----- 156 157 // MutexLocking 158 class MutexLocking { 159 public: 160 inline bool Lock(mutex *lockable) 161 { 162 mutex_lock(lockable); 163 return true; 164 } 165 166 inline void Unlock(mutex *lockable) 167 { 168 mutex_unlock(lockable); 169 } 170 }; 171 172 // MutexLocker 173 typedef AutoLocker<mutex, MutexLocking> MutexLocker; 174 175 // RecursiveLockLocking 176 class RecursiveLockLocking { 177 public: 178 inline bool Lock(recursive_lock *lockable) 179 { 180 recursive_lock_lock(lockable); 181 return true; 182 } 183 184 inline void Unlock(recursive_lock *lockable) 185 { 186 recursive_lock_unlock(lockable); 187 } 188 }; 189 190 // RecursiveLocker 191 typedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker; 192 193 } // namespace BPrivate 194 195 using BPrivate::AutoLocker; 196 using BPrivate::MutexLocker; 197 using BPrivate::RecursiveLocker; 198 199 #endif // KERNEL_UTIL_AUTO_LOCKER_H 200