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
13namespace BPrivate {
14
15
16class RWLockManager;
17
18
19class RWLockable {
20public:
21								RWLockable();
22
23private:
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
43private:
44				thread_id		fOwner;
45				int32			fOwnerCount;
46				int32			fReaderCount;
47				WaiterList		fWaiters;
48};
49
50
51class RWLockManager {
52public:
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
80private:
81			status_t			_Wait(RWLockable* lockable, bool writer,
82									bigtime_t timeout);
83			void				_Unblock(RWLockable* lockable);
84
85private:
86			BLocker				fLock;
87};
88
89
90inline bool
91RWLockManager::GenericLock(bool write, RWLockable* lockable)
92{
93	return write ? WriteLock(lockable) : ReadLock(lockable);
94}
95
96
97inline bool
98RWLockManager::TryGenericLock(bool write, RWLockable* lockable)
99{
100	return write ? TryWriteLock(lockable) : TryReadLock(lockable);
101}
102
103
104inline status_t
105RWLockManager::GenericLockWithTimeout(bool write, RWLockable* lockable,
106	bigtime_t timeout)
107{
108	return write
109		? WriteLockWithTimeout(lockable, timeout)
110		: ReadLockWithTimeout(lockable, timeout);
111}
112
113
114inline void
115RWLockManager::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
127using BPrivate::RWLockable;
128using BPrivate::RWLockManager;
129
130
131#endif	// _RW_LOCK_MANAGER_H
132