1227402f2SIngo Weinhold/*
24535495dSIngo Weinhold * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3227402f2SIngo Weinhold * Distributed under the terms of the MIT License.
4227402f2SIngo Weinhold */
5227402f2SIngo Weinhold#ifndef _KERNEL_CONDITION_VARIABLE_H
6227402f2SIngo Weinhold#define _KERNEL_CONDITION_VARIABLE_H
7227402f2SIngo Weinhold
8227402f2SIngo Weinhold
9227402f2SIngo Weinhold#include <OS.h>
10227402f2SIngo Weinhold
11addece20SIngo Weinhold#include <debug.h>
12addece20SIngo Weinhold
13227402f2SIngo Weinhold#ifdef __cplusplus
14227402f2SIngo Weinhold
158db2e374SIngo Weinhold#include <util/DoublyLinkedList.h>
16227402f2SIngo Weinhold#include <util/OpenHashTable.h>
17227402f2SIngo Weinhold
18227402f2SIngo Weinhold
195ea5f51dSIngo Weinholdstruct ConditionVariable;
20227402f2SIngo Weinhold
21ff308b0bSIngo Weinhold
226cef245eSIngo Weinholdstruct ConditionVariableEntry
236cef245eSIngo Weinhold	: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
24ff308b0bSIngo Weinholdpublic:
25addece20SIngo Weinhold#if KDEBUG
266cef245eSIngo Weinhold	inline						ConditionVariableEntry();
276cef245eSIngo Weinhold	inline						~ConditionVariableEntry();
28addece20SIngo Weinhold#endif
29addece20SIngo Weinhold
30fbe0c27aSIngo Weinhold			bool				Add(const void* object);
31fbe0c27aSIngo Weinhold			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
32023bf5fcSIngo Weinhold			status_t			Wait(const void* object, uint32 flags = 0,
33023bf5fcSIngo Weinhold									bigtime_t timeout = 0);
34ff308b0bSIngo Weinhold
355ee1f125SMichael Lotz	inline	status_t			WaitStatus() const { return fWaitStatus; }
365ee1f125SMichael Lotz
375ee1f125SMichael Lotz	inline	ConditionVariable*	Variable() const { return fVariable; }
386cef245eSIngo Weinhold
39023bf5fcSIngo Weinholdprivate:
40cb919155SAxel Dörfler	inline	void				AddToVariable(ConditionVariable* variable);
41023bf5fcSIngo Weinhold
426cef245eSIngo Weinholdprivate:
436cef245eSIngo Weinhold			ConditionVariable*	fVariable;
444535495dSIngo Weinhold			Thread*				fThread;
45fbe0c27aSIngo Weinhold			status_t			fWaitStatus;
46ff308b0bSIngo Weinhold
475ea5f51dSIngo Weinhold			friend struct ConditionVariable;
48227402f2SIngo Weinhold};
49227402f2SIngo Weinhold
50227402f2SIngo Weinhold
515147963dSStephan Aßmusstruct ConditionVariable {
52227402f2SIngo Weinholdpublic:
53023bf5fcSIngo Weinhold			void				Init(const void* object,
54023bf5fcSIngo Weinhold									const char* objectType);
55023bf5fcSIngo Weinhold									// for anonymous (unpublished) cvars
56023bf5fcSIngo Weinhold
57227402f2SIngo Weinhold			void				Publish(const void* object,
58227402f2SIngo Weinhold									const char* objectType);
5903fb2d88SPawel Dziepak			void				Unpublish();
6003fb2d88SPawel Dziepak
6103fb2d88SPawel Dziepak	inline	void				NotifyOne(status_t result = B_OK);
6203fb2d88SPawel Dziepak	inline	void				NotifyAll(status_t result = B_OK);
6303fb2d88SPawel Dziepak
6403fb2d88SPawel Dziepak	static	void				NotifyOne(const void* object, status_t result);
6503fb2d88SPawel Dziepak	static	void				NotifyAll(const void* object, status_t result);
66f5251d5bSIngo Weinhold									// (both methods) caller must ensure that
67f5251d5bSIngo Weinhold									// the variable is not unpublished
68f5251d5bSIngo Weinhold									// concurrently
691581b764SColin Günther
70cb919155SAxel Dörfler			void				Add(ConditionVariableEntry* entry);
71023bf5fcSIngo Weinhold
725c99d639SIngo Weinhold			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
735c99d639SIngo Weinhold									// all-in one, i.e. doesn't need a
745c99d639SIngo Weinhold									// ConditionVariableEntry
755c99d639SIngo Weinhold
76d5488b77SIngo Weinhold			const void*			Object() const		{ return fObject; }
77d5488b77SIngo Weinhold			const char*			ObjectType() const	{ return fObjectType; }
786cef245eSIngo Weinhold
796cef245eSIngo Weinhold	static	void				ListAll();
806cef245eSIngo Weinhold			void				Dump() const;
81227402f2SIngo Weinhold
82227402f2SIngo Weinholdprivate:
8303fb2d88SPawel Dziepak			void				_Notify(bool all, status_t result);
845ee1f125SMichael Lotz			void				_NotifyLocked(bool all, status_t result);
85227402f2SIngo Weinhold
86227402f2SIngo Weinholdprotected:
876cef245eSIngo Weinhold			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
888db2e374SIngo Weinhold
89227402f2SIngo Weinhold			const void*			fObject;
90227402f2SIngo Weinhold			const char*			fObjectType;
918db2e374SIngo Weinhold			EntryList			fEntries;
925147963dSStephan Aßmus			ConditionVariable*	fNext;
93227402f2SIngo Weinhold
945ea5f51dSIngo Weinhold			friend struct ConditionVariableEntry;
955ea5f51dSIngo Weinhold			friend struct ConditionVariableHashDefinition;
96227402f2SIngo Weinhold};
97227402f2SIngo Weinhold
98227402f2SIngo Weinhold
996cef245eSIngo Weinhold#if KDEBUG
100227402f2SIngo Weinhold
1016cef245eSIngo Weinholdinline
1026cef245eSIngo WeinholdConditionVariableEntry::ConditionVariableEntry()
1036cef245eSIngo Weinhold	: fVariable(NULL)
104227402f2SIngo Weinhold{
105227402f2SIngo Weinhold}
106227402f2SIngo Weinhold
1076cef245eSIngo Weinholdinline
1086cef245eSIngo WeinholdConditionVariableEntry::~ConditionVariableEntry()
109227402f2SIngo Weinhold{
1106cef245eSIngo Weinhold	if (fVariable != NULL) {
1116cef245eSIngo Weinhold		panic("Destroying condition variable entry %p, but it's still "
1126cef245eSIngo Weinhold			"attached to variable %p\n", this, fVariable);
1136cef245eSIngo Weinhold	}
114227402f2SIngo Weinhold}
115227402f2SIngo Weinhold
1166cef245eSIngo Weinhold#endif
117227402f2SIngo Weinhold
118227402f2SIngo Weinhold
119ff308b0bSIngo Weinholdinline void
12003fb2d88SPawel DziepakConditionVariable::NotifyOne(status_t result)
121227402f2SIngo Weinhold{
12203fb2d88SPawel Dziepak	_Notify(false, result);
123227402f2SIngo Weinhold}
124227402f2SIngo Weinhold
125227402f2SIngo Weinhold
1266cef245eSIngo Weinholdinline void
12703fb2d88SPawel DziepakConditionVariable::NotifyAll(status_t result)
128ff308b0bSIngo Weinhold{
12903fb2d88SPawel Dziepak	_Notify(true, result);
130ff308b0bSIngo Weinhold}
131227402f2SIngo Weinhold
132227402f2SIngo Weinhold
133227402f2SIngo Weinholdextern "C" {
134227402f2SIngo Weinhold#endif	// __cplusplus
135227402f2SIngo Weinhold
136227402f2SIngo Weinholdextern void condition_variable_init();
137227402f2SIngo Weinhold
138227402f2SIngo Weinhold#ifdef __cplusplus
139227402f2SIngo Weinhold}	// extern "C"
140227402f2SIngo Weinhold#endif
141227402f2SIngo Weinhold
142227402f2SIngo Weinhold#endif	/* _KERNEL_CONDITION_VARIABLE_H */
143