xref: /haiku/src/servers/app/MultiLocker.h (revision 39c9925fcf718dbb8c8d5342997d6bbd40f9e7e4)
1 /* MultiLocker.h */
2 /*
3 	Copyright 2005-2006, Haiku.
4 	Distributed under the terms of the MIT license.
5 
6 	Copyright 1999, Be Incorporated.   All Rights Reserved.
7 	This file may be used under the terms of the Be Sample Code License.
8 */
9 
10 /** multiple-reader single-writer locking class */
11 
12 // IMPORTANT:
13 //             * nested read locks are not supported
14 //             * a reader becomming the write is not supported
15 //             * nested write locks are supported
16 //             * a writer can do read locks, even nested ones
17 //             * in case of problems, #define DEBUG 1 in the .cpp
18 
19 #ifndef MULTI_LOCKER_H
20 #define MULTI_LOCKER_H
21 
22 //#define TIMING 1
23 
24 #include <OS.h>
25 
26 const int32 LARGE_NUMBER = 100000;
27 
28 class MultiLocker {
29 	public:
30 								MultiLocker(const char* semaphoreBaseName);
31 		virtual					~MultiLocker();
32 
33 		status_t				InitCheck();
34 
35 		//locking for reading or writing
36 		bool					ReadLock();
37 		bool					WriteLock();
38 
39 		//unlocking after reading or writing
40 		bool					ReadUnlock();
41 		bool					WriteUnlock();
42 
43 		//does the current thread hold a write lock ?
44 		bool					IsWriteLocked(uint32 *stack_base = NULL,
45 											  thread_id *thread = NULL);
46 		//in DEBUG mode returns whether the lock is held
47 		//in non-debug mode returns true
48 		bool					IsReadLocked();
49 
50 	private:
51 		//functions for managing the DEBUG reader array
52 		void					register_thread();
53 		void					unregister_thread();
54 
55 		status_t				fInit;
56 		//readers adjust count and block on fReadSem when a writer
57 		//hold the lock
58 		int32					fReadCount;
59 		sem_id					fReadSem;
60 		//writers adjust the count and block on fWriteSem
61 		//when readers hold the lock
62 		int32					fWriteCount;
63 		sem_id 					fWriteSem;
64 		//writers must acquire fWriterLock when acquiring a write lock
65 		int32					fLockCount;
66 		sem_id					fWriterLock;
67 		int32					fWriterNest;
68 
69 		thread_id				fWriterThread;
70 		uint32					fWriterStackBase;
71 
72 		int32 *					fDebugArray;
73 		int32					fMaxThreads;
74 
75 #if TIMING
76 		uint32 					rl_count;
77 		bigtime_t 				rl_time;
78 		uint32 					ru_count;
79 		bigtime_t 				ru_time;
80 		uint32					wl_count;
81 		bigtime_t				wl_time;
82 		uint32					wu_count;
83 		bigtime_t				wu_time;
84 		uint32					islock_count;
85 		bigtime_t				islock_time;
86 		uint32					reg_count;
87 		bigtime_t				reg_time;
88 		uint32					unreg_count;
89 		bigtime_t				unreg_time;
90 #endif
91 };
92 
93 class AutoWriteLocker {
94  public:
95 								AutoWriteLocker(MultiLocker* lock)
96 									: fLock(*lock)
97 								{
98 									fLock.WriteLock();
99 								}
100 								AutoWriteLocker(MultiLocker& lock)
101 									: fLock(lock)
102 								{
103 									fLock.WriteLock();
104 								}
105 								~AutoWriteLocker()
106 								{
107 									fLock.WriteUnlock();
108 								}
109  private:
110 	 	MultiLocker&			fLock;
111 };
112 
113 class AutoReadLocker {
114  public:
115 								AutoReadLocker(MultiLocker* lock)
116 									: fLock(*lock)
117 								{
118 									fLock.ReadLock();
119 								}
120 								AutoReadLocker(MultiLocker& lock)
121 									: fLock(lock)
122 								{
123 									fLock.ReadLock();
124 								}
125 								~AutoReadLocker()
126 								{
127 									fLock.ReadUnlock();
128 								}
129  private:
130 	 	MultiLocker&			fLock;
131 };
132 
133 
134 
135 #endif
136