xref: /haiku/headers/private/kernel/condition_variable.h (revision a2db5acb28c0635849a76467faac1e94f6c55659)
1 /*
2  * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _KERNEL_CONDITION_VARIABLE_H
6 #define _KERNEL_CONDITION_VARIABLE_H
7 
8 
9 #include <OS.h>
10 
11 #include <debug.h>
12 
13 #ifdef __cplusplus
14 
15 #include <util/OpenHashTable.h>
16 
17 
18 class PrivateConditionVariable;
19 
20 
21 struct PrivateConditionVariableEntry {
22 public:
23 #if KDEBUG
24 	inline PrivateConditionVariableEntry()
25 		: fVariable(NULL)
26 	{
27 	}
28 
29 	inline ~PrivateConditionVariableEntry()
30 	{
31 		if (fVariable != NULL) {
32 			panic("Destroying condition variable entry %p, but it's still "
33 				"attached to variable %p\n", this, fVariable);
34 		}
35 	}
36 #endif
37 
38 	inline	PrivateConditionVariable* Variable() const
39 		{ return fVariable; }
40 
41 	inline	PrivateConditionVariableEntry* ThreadNext() const
42 		{ return fThreadNext; }
43 	inline	PrivateConditionVariableEntry* ThreadPrevious() const
44 		{ return fThreadPrevious; }
45 
46 	class Private;
47 
48 protected:
49 			bool				Add(const void* object,
50 									PrivateConditionVariableEntry* threadNext);
51 			status_t			Wait(uint32 flags);
52 			status_t			Wait(const void* object, uint32 flags);
53 
54 private:
55 			void				_Remove();
56 
57 protected:
58 			PrivateConditionVariableEntry* fVariableNext;
59 			PrivateConditionVariable* fVariable;
60 			struct thread*		fThread;
61 			uint32				fFlags;
62 			status_t			fResult;
63 
64 			PrivateConditionVariableEntry* fThreadPrevious;
65 			PrivateConditionVariableEntry* fThreadNext;
66 
67 			friend class PrivateConditionVariable;
68 			friend class Private;
69 };
70 
71 
72 class PrivateConditionVariable
73 	: protected HashTableLink<PrivateConditionVariable> {
74 public:
75 	static	void				ListAll();
76 			void				Dump();
77 
78 protected:
79 			void				Publish(const void* object,
80 									const char* objectType);
81 			void				Unpublish(bool threadsLocked);
82 			void				Notify(bool all, bool threadsLocked);
83 
84 private:
85 			void				_Notify(bool all, status_t result);
86 
87 protected:
88 			const void*			fObject;
89 			const char*			fObjectType;
90 			PrivateConditionVariableEntry* fEntries;
91 
92 			friend class PrivateConditionVariableEntry;
93 			friend class ConditionVariableHashDefinition;
94 };
95 
96 
97 template<typename Type = void>
98 class ConditionVariable : private PrivateConditionVariable {
99 public:
100 	inline	void				Publish(const Type* object,
101 									const char* objectType);
102 
103 	inline	void				Unpublish(bool threadsLocked = false);
104 	inline	void				NotifyOne(bool threadsLocked = false);
105 	inline	void				NotifyAll(bool threadsLocked = false);
106 };
107 
108 
109 template<typename Type = void>
110 class ConditionVariableEntry : public PrivateConditionVariableEntry {
111 public:
112 	inline	bool				Add(const Type* object,
113 									PrivateConditionVariableEntry* threadNext
114 										= NULL);
115 	inline	status_t			Wait(uint32 flags = 0);
116 	inline	status_t			Wait(const Type* object, uint32 flags = 0);
117 };
118 
119 
120 template<typename Type>
121 inline void
122 ConditionVariable<Type>::Publish(const Type* object, const char* objectType)
123 {
124 	PrivateConditionVariable::Publish(object, objectType);
125 }
126 
127 
128 template<typename Type>
129 inline void
130 ConditionVariable<Type>::Unpublish(bool threadsLocked)
131 {
132 	PrivateConditionVariable::Unpublish(threadsLocked);
133 }
134 
135 
136 template<typename Type>
137 inline void
138 ConditionVariable<Type>::NotifyOne(bool threadsLocked)
139 {
140 	PrivateConditionVariable::Notify(false, threadsLocked);
141 }
142 
143 
144 template<typename Type>
145 inline void
146 ConditionVariable<Type>::NotifyAll(bool threadsLocked)
147 {
148 	PrivateConditionVariable::Notify(true, threadsLocked);
149 }
150 
151 
152 template<typename Type>
153 inline bool
154 ConditionVariableEntry<Type>::Add(const Type* object,
155 	PrivateConditionVariableEntry* threadNext)
156 {
157 	return PrivateConditionVariableEntry::Add(object, threadNext);
158 }
159 
160 
161 template<typename Type>
162 inline status_t
163 ConditionVariableEntry<Type>::Wait(uint32 flags)
164 {
165 	return PrivateConditionVariableEntry::Wait(flags);
166 }
167 
168 
169 template<typename Type>
170 inline status_t
171 ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags)
172 {
173 	return PrivateConditionVariableEntry::Wait(object, flags);
174 }
175 
176 
177 extern "C" {
178 #endif	// __cplusplus
179 
180 struct thread;
181 
182 extern status_t condition_variable_interrupt_thread(struct thread* thread);
183 
184 extern void condition_variable_init();
185 
186 #ifdef __cplusplus
187 }	// extern "C"
188 #endif
189 
190 #endif	/* _KERNEL_CONDITION_VARIABLE_H */
191