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
19struct ConditionVariable;
20
21
22struct ConditionVariableEntry
23	: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
24public:
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
39private:
40	inline	void				AddToVariable(ConditionVariable* variable);
41
42private:
43			ConditionVariable*	fVariable;
44			Thread*				fThread;
45			status_t			fWaitStatus;
46
47			friend struct ConditionVariable;
48};
49
50
51struct ConditionVariable {
52public:
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
88private:
89			void				_Notify(bool all, bool schedulerLocked,
90									status_t result);
91			void				_NotifyLocked(bool all, status_t result);
92
93protected:
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
108inline
109ConditionVariableEntry::ConditionVariableEntry()
110	: fVariable(NULL)
111{
112}
113
114inline
115ConditionVariableEntry::~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
126inline void
127ConditionVariable::NotifyOne(bool schedulerLocked, status_t result)
128{
129	_Notify(false, schedulerLocked, result);
130}
131
132
133inline void
134ConditionVariable::NotifyAll(bool schedulerLocked, status_t result)
135{
136	_Notify(true, schedulerLocked, result);
137}
138
139
140extern "C" {
141#endif	// __cplusplus
142
143extern void condition_variable_init();
144
145#ifdef __cplusplus
146}	// extern "C"
147#endif
148
149#endif	/* _KERNEL_CONDITION_VARIABLE_H */
150