1227402f2SIngo Weinhold/*
24535495dSIngo Weinhold * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
337eda488SAugustin Cavalier * Copyright 2019, Haiku, Inc. All rights reserved.
4227402f2SIngo Weinhold * Distributed under the terms of the MIT License.
5227402f2SIngo Weinhold */
6227402f2SIngo Weinhold#ifndef _KERNEL_CONDITION_VARIABLE_H
7227402f2SIngo Weinhold#define _KERNEL_CONDITION_VARIABLE_H
8227402f2SIngo Weinhold
9227402f2SIngo Weinhold
10227402f2SIngo Weinhold#include <OS.h>
11227402f2SIngo Weinhold
12addece20SIngo Weinhold#include <debug.h>
13addece20SIngo Weinhold
14227402f2SIngo Weinhold#ifdef __cplusplus
15227402f2SIngo Weinhold
168db2e374SIngo Weinhold#include <util/DoublyLinkedList.h>
17227402f2SIngo Weinhold#include <util/OpenHashTable.h>
18227402f2SIngo Weinhold
19227402f2SIngo Weinhold
205ea5f51dSIngo Weinholdstruct ConditionVariable;
21227402f2SIngo Weinhold
22ff308b0bSIngo Weinhold
236cef245eSIngo Weinholdstruct ConditionVariableEntry
246cef245eSIngo Weinhold	: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
25ff308b0bSIngo Weinholdpublic:
26addece20SIngo Weinhold#if KDEBUG
276cef245eSIngo Weinhold	inline						ConditionVariableEntry();
286cef245eSIngo Weinhold	inline						~ConditionVariableEntry();
29addece20SIngo Weinhold#endif
30addece20SIngo Weinhold
31fbe0c27aSIngo Weinhold			bool				Add(const void* object);
32fbe0c27aSIngo Weinhold			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
33023bf5fcSIngo Weinhold			status_t			Wait(const void* object, uint32 flags = 0,
34023bf5fcSIngo Weinhold									bigtime_t timeout = 0);
35ff308b0bSIngo Weinhold
365ee1f125SMichael Lotz	inline	status_t			WaitStatus() const { return fWaitStatus; }
375ee1f125SMichael Lotz
385ee1f125SMichael Lotz	inline	ConditionVariable*	Variable() const { return fVariable; }
396cef245eSIngo Weinhold
40023bf5fcSIngo Weinholdprivate:
4137eda488SAugustin Cavalier	inline	void				AddToLockedVariable(ConditionVariable* variable);
42023bf5fcSIngo Weinhold
436cef245eSIngo Weinholdprivate:
4437eda488SAugustin Cavalier			spinlock			fLock;
456cef245eSIngo Weinhold			ConditionVariable*	fVariable;
464535495dSIngo Weinhold			Thread*				fThread;
47fbe0c27aSIngo Weinhold			status_t			fWaitStatus;
48ff308b0bSIngo Weinhold
495ea5f51dSIngo Weinhold			friend struct ConditionVariable;
50227402f2SIngo Weinhold};
51227402f2SIngo Weinhold
52227402f2SIngo Weinhold
535147963dSStephan Aßmusstruct ConditionVariable {
54227402f2SIngo Weinholdpublic:
55023bf5fcSIngo Weinhold			void				Init(const void* object,
56023bf5fcSIngo Weinhold									const char* objectType);
57023bf5fcSIngo Weinhold									// for anonymous (unpublished) cvars
58023bf5fcSIngo Weinhold
59227402f2SIngo Weinhold			void				Publish(const void* object,
60227402f2SIngo Weinhold									const char* objectType);
6103fb2d88SPawel Dziepak			void				Unpublish();
6203fb2d88SPawel Dziepak
6303fb2d88SPawel Dziepak	inline	void				NotifyOne(status_t result = B_OK);
6403fb2d88SPawel Dziepak	inline	void				NotifyAll(status_t result = B_OK);
6503fb2d88SPawel Dziepak
6603fb2d88SPawel Dziepak	static	void				NotifyOne(const void* object, status_t result);
6703fb2d88SPawel Dziepak	static	void				NotifyAll(const void* object, status_t result);
68f5251d5bSIngo Weinhold									// (both methods) caller must ensure that
69f5251d5bSIngo Weinhold									// the variable is not unpublished
70f5251d5bSIngo Weinhold									// concurrently
711581b764SColin Günther
72cb919155SAxel Dörfler			void				Add(ConditionVariableEntry* entry);
73023bf5fcSIngo Weinhold
745c99d639SIngo Weinhold			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
755c99d639SIngo Weinhold									// all-in one, i.e. doesn't need a
765c99d639SIngo Weinhold									// ConditionVariableEntry
775c99d639SIngo Weinhold
78d5488b77SIngo Weinhold			const void*			Object() const		{ return fObject; }
79d5488b77SIngo Weinhold			const char*			ObjectType() const	{ return fObjectType; }
806cef245eSIngo Weinhold
816cef245eSIngo Weinhold	static	void				ListAll();
826cef245eSIngo Weinhold			void				Dump() const;
83227402f2SIngo Weinhold
84227402f2SIngo Weinholdprivate:
8503fb2d88SPawel Dziepak			void				_Notify(bool all, status_t result);
865ee1f125SMichael Lotz			void				_NotifyLocked(bool all, status_t result);
87227402f2SIngo Weinhold
88227402f2SIngo Weinholdprotected:
896cef245eSIngo Weinhold			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
908db2e374SIngo Weinhold
91227402f2SIngo Weinhold			const void*			fObject;
92227402f2SIngo Weinhold			const char*			fObjectType;
9337eda488SAugustin Cavalier
9437eda488SAugustin Cavalier			spinlock			fLock;
958db2e374SIngo Weinhold			EntryList			fEntries;
965147963dSStephan Aßmus			ConditionVariable*	fNext;
97227402f2SIngo Weinhold
985ea5f51dSIngo Weinhold			friend struct ConditionVariableEntry;
995ea5f51dSIngo Weinhold			friend struct ConditionVariableHashDefinition;
100227402f2SIngo Weinhold};
101227402f2SIngo Weinhold
102227402f2SIngo Weinhold
1036cef245eSIngo Weinhold#if KDEBUG
104227402f2SIngo Weinhold
1056cef245eSIngo Weinholdinline
1066cef245eSIngo WeinholdConditionVariableEntry::ConditionVariableEntry()
1076cef245eSIngo Weinhold	: fVariable(NULL)
108227402f2SIngo Weinhold{
109227402f2SIngo Weinhold}
110227402f2SIngo Weinhold
1116cef245eSIngo Weinholdinline
1126cef245eSIngo WeinholdConditionVariableEntry::~ConditionVariableEntry()
113227402f2SIngo Weinhold{
1146cef245eSIngo Weinhold	if (fVariable != NULL) {
1156cef245eSIngo Weinhold		panic("Destroying condition variable entry %p, but it's still "
1166cef245eSIngo Weinhold			"attached to variable %p\n", this, fVariable);
1176cef245eSIngo Weinhold	}
118227402f2SIngo Weinhold}
119227402f2SIngo Weinhold
1206cef245eSIngo Weinhold#endif
121227402f2SIngo Weinhold
122227402f2SIngo Weinhold
123ff308b0bSIngo Weinholdinline void
12403fb2d88SPawel DziepakConditionVariable::NotifyOne(status_t result)
125227402f2SIngo Weinhold{
12603fb2d88SPawel Dziepak	_Notify(false, result);
127227402f2SIngo Weinhold}
128227402f2SIngo Weinhold
129227402f2SIngo Weinhold
1306cef245eSIngo Weinholdinline void
13103fb2d88SPawel DziepakConditionVariable::NotifyAll(status_t result)
132ff308b0bSIngo Weinhold{
13303fb2d88SPawel Dziepak	_Notify(true, result);
134ff308b0bSIngo Weinhold}
135227402f2SIngo Weinhold
136227402f2SIngo Weinhold
137227402f2SIngo Weinholdextern "C" {
138227402f2SIngo Weinhold#endif	// __cplusplus
139227402f2SIngo Weinhold
140227402f2SIngo Weinholdextern void condition_variable_init();
141227402f2SIngo Weinhold
142227402f2SIngo Weinhold#ifdef __cplusplus
143227402f2SIngo Weinhold}	// extern "C"
144227402f2SIngo Weinhold#endif
145227402f2SIngo Weinhold
146227402f2SIngo Weinhold#endif	/* _KERNEL_CONDITION_VARIABLE_H */
147