xref: /haiku/headers/private/kernel/condition_variable.h (revision e9c9b2e448ad9026f9e6704d80f5afefd0ce8aa6)
1 /*
2  * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2019-2024, 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 
20 struct mutex;
21 struct recursive_lock;
22 struct ConditionVariable;
23 
24 
25 struct ConditionVariableEntry
26 	: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
27 public:
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 
38 private:
39 	inline	void				_AddToLockedVariable(ConditionVariable* variable);
40 			void				_RemoveFromVariable();
41 
42 private:
43 			ConditionVariable*	fVariable;
44 			Thread*				fThread;
45 			status_t			fWaitStatus;
46 
47 			friend struct ConditionVariable;
48 };
49 
50 
51 struct ConditionVariable {
52 public:
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);
EntriesCountConditionVariable68 			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 
ObjectConditionVariable75 			const void*			Object() const		{ return fObject; }
ObjectTypeConditionVariable76 			const char*			ObjectType() const	{ return fObjectType; }
77 
78 	// Debug methods.
79 	static	void				ListAll();
80 			void				Dump() const;
81 	static	status_t			DebugGetType(ConditionVariable* cvar, char* name, size_t size);
82 
83 private:
84 	static 	int32				_Notify(const void* object, bool all, status_t result);
85 			int32				_Notify(bool all, status_t result);
86 			int32				_NotifyLocked(bool all, status_t result);
87 
88 protected:
89 			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
90 
91 			ConditionVariable*	fNext;
92 
93 			const void*			fObject;
94 			const char*			fObjectType;
95 
96 			spinlock			fLock;
97 			int32				fEntriesCount;
98 			EntryList			fEntries;
99 
100 			friend struct ConditionVariableEntry;
101 			friend struct ConditionVariableHashDefinition;
102 };
103 
104 
105 inline int32
NotifyOne(status_t result)106 ConditionVariable::NotifyOne(status_t result)
107 {
108 	return _Notify(false, result);
109 }
110 
111 
112 inline int32
NotifyAll(status_t result)113 ConditionVariable::NotifyAll(status_t result)
114 {
115 	return _Notify(true, result);
116 }
117 
118 
119 extern "C" {
120 #endif	// __cplusplus
121 
122 extern void condition_variable_init();
123 
124 #ifdef __cplusplus
125 }	// extern "C"
126 #endif
127 
128 #endif	/* _KERNEL_CONDITION_VARIABLE_H */
129