1/*
2 * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2019, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6#ifndef _KERNEL_CONDITION_VARIABLE_H
7#define _KERNEL_CONDITION_VARIABLE_H
8
9
10#include <OS.h>
11
12#include <debug.h>
13
14#ifdef __cplusplus
15
16#include <util/DoublyLinkedList.h>
17#include <util/OpenHashTable.h>
18
19
20struct mutex;
21struct recursive_lock;
22struct ConditionVariable;
23
24
25struct ConditionVariableEntry
26	: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
27public:
28								ConditionVariableEntry();
29								~ConditionVariableEntry();
30
31			bool				Add(const void* object);
32			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
33			status_t			Wait(const void* object, uint32 flags = 0,
34									bigtime_t timeout = 0);
35
36			ConditionVariable*	Variable() const;
37
38private:
39	inline	void				_AddToLockedVariable(ConditionVariable* variable);
40			void				_RemoveFromVariable();
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	int32				NotifyOne(status_t result = B_OK);
62	inline	int32				NotifyAll(status_t result = B_OK);
63
64	static	int32				NotifyOne(const void* object, status_t result);
65	static	int32				NotifyAll(const void* object, status_t result);
66
67			void				Add(ConditionVariableEntry* entry);
68			int32				EntriesCount()		{ return atomic_get(&fEntriesCount); }
69
70	// Convenience methods, no ConditionVariableEntry required.
71			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
72			status_t			Wait(mutex* lock, uint32 flags = 0, bigtime_t timeout = 0);
73			status_t			Wait(recursive_lock* lock, uint32 flags = 0, bigtime_t timeout = 0);
74
75			const void*			Object() const		{ return fObject; }
76			const char*			ObjectType() const	{ return fObjectType; }
77
78	static	void				ListAll();
79			void				Dump() const;
80
81private:
82	static 	int32				_Notify(const void* object, bool all, status_t result);
83			int32				_Notify(bool all, status_t result);
84			int32				_NotifyLocked(bool all, status_t result);
85
86protected:
87			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
88
89			ConditionVariable*	fNext;
90
91			const void*			fObject;
92			const char*			fObjectType;
93
94			spinlock			fLock;
95			int32				fEntriesCount;
96			EntryList			fEntries;
97
98			friend struct ConditionVariableEntry;
99			friend struct ConditionVariableHashDefinition;
100			friend ssize_t debug_condition_variable_type_strlcpy(ConditionVariable* cvar,
101				char* name, size_t size);
102};
103
104
105inline int32
106ConditionVariable::NotifyOne(status_t result)
107{
108	return _Notify(false, result);
109}
110
111
112inline int32
113ConditionVariable::NotifyAll(status_t result)
114{
115	return _Notify(true, result);
116}
117
118
119extern "C" {
120#endif	// __cplusplus
121
122extern void condition_variable_init();
123
124#ifdef __cplusplus
125}	// extern "C"
126#endif
127
128#endif	/* _KERNEL_CONDITION_VARIABLE_H */
129