xref: /haiku/headers/private/kernel/condition_variable.h (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
1 /*
2  * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.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/DoublyLinkedList.h>
16 #include <util/OpenHashTable.h>
17 
18 
19 struct ConditionVariable;
20 
21 
22 struct ConditionVariableEntry
23 	: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
24 public:
25 #if KDEBUG
26 	inline						ConditionVariableEntry();
27 	inline						~ConditionVariableEntry();
28 #endif
29 
30 			bool				Add(const void* object);
31 			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
32 			status_t			Wait(const void* object, uint32 flags = 0,
33 									bigtime_t timeout = 0);
34 
35 	inline	status_t			WaitStatus() const { return fWaitStatus; }
36 
37 	inline	ConditionVariable*	Variable() const { return fVariable; }
38 
39 private:
40 	inline	void				AddToVariable(ConditionVariable* variable);
41 
42 private:
43 			ConditionVariable*	fVariable;
44 			Thread*				fThread;
45 			status_t			fWaitStatus;
46 
47 			friend struct ConditionVariable;
48 };
49 
50 
51 struct ConditionVariable {
52 public:
53 			void				Init(const void* object,
54 									const char* objectType);
55 									// for anonymous (unpublished) cvars
56 
57 			void				Publish(const void* object,
58 									const char* objectType);
59 			void				Unpublish(bool schedulerLocked = false);
60 
61 	inline	void				NotifyOne(bool schedulerLocked = false,
62 									status_t result = B_OK);
63 	inline	void				NotifyAll(bool schedulerLocked = false,
64 									status_t result = B_OK);
65 
66 	static	void				NotifyOne(const void* object,
67 									bool schedulerLocked = false,
68 									status_t result = B_OK);
69 	static	void				NotifyAll(const void* object,
70 									bool schedulerLocked = false,
71 									status_t result = B_OK);
72 									// (both methods) caller must ensure that
73 									// the variable is not unpublished
74 									// concurrently
75 
76 			void				Add(ConditionVariableEntry* entry);
77 
78 			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
79 									// all-in one, i.e. doesn't need a
80 									// ConditionVariableEntry
81 
82 			const void*			Object() const		{ return fObject; }
83 			const char*			ObjectType() const	{ return fObjectType; }
84 
85 	static	void				ListAll();
86 			void				Dump() const;
87 
88 private:
89 			void				_Notify(bool all, bool schedulerLocked,
90 									status_t result);
91 			void				_NotifyLocked(bool all, status_t result);
92 
93 protected:
94 			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
95 
96 			const void*			fObject;
97 			const char*			fObjectType;
98 			EntryList			fEntries;
99 			ConditionVariable*	fNext;
100 
101 			friend struct ConditionVariableEntry;
102 			friend struct ConditionVariableHashDefinition;
103 };
104 
105 
106 #if KDEBUG
107 
108 inline
109 ConditionVariableEntry::ConditionVariableEntry()
110 	: fVariable(NULL)
111 {
112 }
113 
114 inline
115 ConditionVariableEntry::~ConditionVariableEntry()
116 {
117 	if (fVariable != NULL) {
118 		panic("Destroying condition variable entry %p, but it's still "
119 			"attached to variable %p\n", this, fVariable);
120 	}
121 }
122 
123 #endif
124 
125 
126 inline void
127 ConditionVariable::NotifyOne(bool schedulerLocked, status_t result)
128 {
129 	_Notify(false, schedulerLocked, result);
130 }
131 
132 
133 inline void
134 ConditionVariable::NotifyAll(bool schedulerLocked, status_t result)
135 {
136 	_Notify(true, schedulerLocked, result);
137 }
138 
139 
140 extern "C" {
141 #endif	// __cplusplus
142 
143 extern void condition_variable_init();
144 
145 #ifdef __cplusplus
146 }	// extern "C"
147 #endif
148 
149 #endif	/* _KERNEL_CONDITION_VARIABLE_H */
150