xref: /haiku/headers/private/shared/RWLockManager.h (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
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