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();
60
61	inline	void				NotifyOne(status_t result = B_OK);
62	inline	void				NotifyAll(status_t result = B_OK);
63
64	static	void				NotifyOne(const void* object, status_t result);
65	static	void				NotifyAll(const void* object, status_t result);
66									// (both methods) caller must ensure that
67									// the variable is not unpublished
68									// concurrently
69
70			void				Add(ConditionVariableEntry* entry);
71
72			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
73									// all-in one, i.e. doesn't need a
74									// ConditionVariableEntry
75
76			const void*			Object() const		{ return fObject; }
77			const char*			ObjectType() const	{ return fObjectType; }
78
79	static	void				ListAll();
80			void				Dump() const;
81
82private:
83			void				_Notify(bool all, status_t result);
84			void				_NotifyLocked(bool all, status_t result);
85
86protected:
87			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
88
89			const void*			fObject;
90			const char*			fObjectType;
91			EntryList			fEntries;
92			ConditionVariable*	fNext;
93
94			friend struct ConditionVariableEntry;
95			friend struct ConditionVariableHashDefinition;
96};
97
98
99#if KDEBUG
100
101inline
102ConditionVariableEntry::ConditionVariableEntry()
103	: fVariable(NULL)
104{
105}
106
107inline
108ConditionVariableEntry::~ConditionVariableEntry()
109{
110	if (fVariable != NULL) {
111		panic("Destroying condition variable entry %p, but it's still "
112			"attached to variable %p\n", this, fVariable);
113	}
114}
115
116#endif
117
118
119inline void
120ConditionVariable::NotifyOne(status_t result)
121{
122	_Notify(false, result);
123}
124
125
126inline void
127ConditionVariable::NotifyAll(status_t result)
128{
129	_Notify(true, result);
130}
131
132
133extern "C" {
134#endif	// __cplusplus
135
136extern void condition_variable_init();
137
138#ifdef __cplusplus
139}	// extern "C"
140#endif
141
142#endif	/* _KERNEL_CONDITION_VARIABLE_H */
143