1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _RW_LOCK_MANAGER_H 6 #define _RW_LOCK_MANAGER_H 7 8 #include <Locker.h> 9 10 #include <util/DoublyLinkedList.h> 11 12 13 namespace BPrivate { 14 15 16 class RWLockManager; 17 18 19 class RWLockable { 20 public: 21 RWLockable(); 22 23 private: 24 struct Waiter : DoublyLinkedListLinkImpl<Waiter> { 25 Waiter(bool writer) 26 : 27 thread(find_thread(NULL)), 28 writer(writer), 29 queued(false) 30 { 31 } 32 33 thread_id thread; 34 status_t status; 35 bool writer; 36 bool queued; 37 }; 38 39 typedef DoublyLinkedList<Waiter> WaiterList; 40 41 friend class RWLockManager; 42 43 private: 44 thread_id fOwner; 45 int32 fOwnerCount; 46 int32 fReaderCount; 47 WaiterList fWaiters; 48 }; 49 50 51 class RWLockManager { 52 public: 53 RWLockManager(); 54 ~RWLockManager(); 55 56 status_t Init() { return fLock.InitCheck(); } 57 58 bool Lock() { return fLock.Lock(); } 59 void Unlock() { return fLock.Unlock(); } 60 61 bool ReadLock(RWLockable* lockable); 62 bool TryReadLock(RWLockable* lockable); 63 status_t ReadLockWithTimeout(RWLockable* lockable, 64 bigtime_t timeout); 65 void ReadUnlock(RWLockable* lockable); 66 67 bool WriteLock(RWLockable* lockable); 68 bool TryWriteLock(RWLockable* lockable); 69 status_t WriteLockWithTimeout(RWLockable* lockable, 70 bigtime_t timeout); 71 void WriteUnlock(RWLockable* lockable); 72 73 inline bool GenericLock(bool write, RWLockable* lockable); 74 inline bool TryGenericLock(bool write, 75 RWLockable* lockable); 76 inline status_t GenericLockWithTimeout(bool write, 77 RWLockable* lockable, bigtime_t timeout); 78 inline void GenericUnlock(bool write, RWLockable* lockable); 79 80 private: 81 status_t _Wait(RWLockable* lockable, bool writer, 82 bigtime_t timeout); 83 void _Unblock(RWLockable* lockable); 84 85 private: 86 BLocker fLock; 87 }; 88 89 90 inline bool 91 RWLockManager::GenericLock(bool write, RWLockable* lockable) 92 { 93 return write ? WriteLock(lockable) : ReadLock(lockable); 94 } 95 96 97 inline bool 98 RWLockManager::TryGenericLock(bool write, RWLockable* lockable) 99 { 100 return write ? TryWriteLock(lockable) : TryReadLock(lockable); 101 } 102 103 104 inline status_t 105 RWLockManager::GenericLockWithTimeout(bool write, RWLockable* lockable, 106 bigtime_t timeout) 107 { 108 return write 109 ? WriteLockWithTimeout(lockable, timeout) 110 : ReadLockWithTimeout(lockable, timeout); 111 } 112 113 114 inline void 115 RWLockManager::GenericUnlock(bool write, RWLockable* lockable) 116 { 117 if (write) 118 WriteUnlock(lockable); 119 else 120 ReadUnlock(lockable); 121 } 122 123 124 } // namespace BPrivate 125 126 127 using BPrivate::RWLockable; 128 using BPrivate::RWLockManager; 129 130 131 #endif // _RW_LOCK_MANAGER_H 132