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> {
WaiterWaiter25 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
Init()56 status_t Init() { return fLock.InitCheck(); }
57
Lock()58 bool Lock() { return fLock.Lock(); }
Unlock()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
GenericLock(bool write,RWLockable * lockable)91 RWLockManager::GenericLock(bool write, RWLockable* lockable)
92 {
93 return write ? WriteLock(lockable) : ReadLock(lockable);
94 }
95
96
97 inline bool
TryGenericLock(bool write,RWLockable * lockable)98 RWLockManager::TryGenericLock(bool write, RWLockable* lockable)
99 {
100 return write ? TryWriteLock(lockable) : TryReadLock(lockable);
101 }
102
103
104 inline status_t
GenericLockWithTimeout(bool write,RWLockable * lockable,bigtime_t timeout)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
GenericUnlock(bool write,RWLockable * lockable)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