xref: /haiku/headers/private/kernel/condition_variable.h (revision 079c69cbfd7cd3c97baae91332251c8388a8bb02)
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, bool threadsLocked,
86 									status_t result);
87 
88 protected:
89 			const void*			fObject;
90 			const char*			fObjectType;
91 			PrivateConditionVariableEntry* fEntries;
92 
93 			friend class PrivateConditionVariableEntry;
94 			friend class ConditionVariableHashDefinition;
95 };
96 
97 
98 template<typename Type>
99 class ConditionVariable : private PrivateConditionVariable {
100 public:
101 	inline	void				Publish(const Type* object,
102 									const char* objectType);
103 
104 	inline	void				Unpublish(bool threadsLocked = false);
105 	inline	void				NotifyOne(bool threadsLocked = false);
106 	inline	void				NotifyAll(bool threadsLocked = false);
107 };
108 
109 
110 template<typename Type>
111 class ConditionVariableEntry : public PrivateConditionVariableEntry {
112 public:
113 	inline	bool				Add(const Type* object,
114 									PrivateConditionVariableEntry* threadNext
115 										= NULL);
116 	inline	status_t			Wait(uint32 flags = 0);
117 	inline	status_t			Wait(const Type* object, uint32 flags = 0);
118 };
119 
120 
121 template<typename Type>
122 inline void
123 ConditionVariable<Type>::Publish(const Type* object, const char* objectType)
124 {
125 	PrivateConditionVariable::Publish(object, objectType);
126 }
127 
128 
129 template<typename Type>
130 inline void
131 ConditionVariable<Type>::Unpublish(bool threadsLocked)
132 {
133 	PrivateConditionVariable::Unpublish(threadsLocked);
134 }
135 
136 
137 template<typename Type>
138 inline void
139 ConditionVariable<Type>::NotifyOne(bool threadsLocked)
140 {
141 	PrivateConditionVariable::Notify(false, threadsLocked);
142 }
143 
144 
145 template<typename Type>
146 inline void
147 ConditionVariable<Type>::NotifyAll(bool threadsLocked)
148 {
149 	PrivateConditionVariable::Notify(true, threadsLocked);
150 }
151 
152 
153 template<typename Type>
154 inline bool
155 ConditionVariableEntry<Type>::Add(const Type* object,
156 	PrivateConditionVariableEntry* threadNext)
157 {
158 	return PrivateConditionVariableEntry::Add(object, threadNext);
159 }
160 
161 
162 template<typename Type>
163 inline status_t
164 ConditionVariableEntry<Type>::Wait(uint32 flags)
165 {
166 	return PrivateConditionVariableEntry::Wait(flags);
167 }
168 
169 
170 template<typename Type>
171 inline status_t
172 ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags)
173 {
174 	return PrivateConditionVariableEntry::Wait(object, flags);
175 }
176 
177 
178 extern "C" {
179 #endif	// __cplusplus
180 
181 struct thread;
182 
183 extern status_t condition_variable_interrupt_thread(struct thread* thread);
184 
185 extern void condition_variable_init();
186 
187 #ifdef __cplusplus
188 }	// extern "C"
189 #endif
190 
191 #endif	/* _KERNEL_CONDITION_VARIABLE_H */
192