xref: /haiku/headers/private/kernel/condition_variable.h (revision 2d6d3938e72b06da2e6298c1ad6b70da5338fa4a)
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 
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 	inline	status_t			WaitStatus() const { return fWaitStatus; }
37 
38 	inline	ConditionVariable*	Variable() const { return fVariable; }
39 
40 private:
41 	inline	void				_AddToLockedVariable(ConditionVariable* variable);
42 			void				_RemoveFromVariable();
43 
44 private:
45 			ConditionVariable*	fVariable;
46 			Thread*				fThread;
47 			status_t			fWaitStatus;
48 
49 			friend struct ConditionVariable;
50 };
51 
52 
53 struct ConditionVariable {
54 public:
55 			void				Init(const void* object,
56 									const char* objectType);
57 									// for anonymous (unpublished) cvars
58 
59 			void				Publish(const void* object,
60 									const char* objectType);
61 			void				Unpublish();
62 
63 	inline	void				NotifyOne(status_t result = B_OK);
64 	inline	void				NotifyAll(status_t result = B_OK);
65 
66 	static	void				NotifyOne(const void* object, status_t result);
67 	static	void				NotifyAll(const void* object, status_t result);
68 									// (both methods) caller must ensure that
69 									// the variable is not unpublished
70 									// concurrently
71 
72 			void				Add(ConditionVariableEntry* entry);
73 
74 			status_t			Wait(uint32 flags = 0, bigtime_t timeout = 0);
75 									// all-in one, i.e. doesn't need a
76 									// ConditionVariableEntry
77 			status_t			Wait(mutex* lock, uint32 flags = 0, bigtime_t timeout = 0);
78 			status_t			Wait(recursive_lock* lock, uint32 flags = 0, bigtime_t timeout = 0);
79 			status_t			Wait(spinlock* lock, uint32 flags = 0, bigtime_t timeout = 0);
80 
81 			const void*			Object() const		{ return fObject; }
82 			const char*			ObjectType() const	{ return fObjectType; }
83 
84 	static	void				ListAll();
85 			void				Dump() const;
86 
87 private:
88 			void				_Notify(bool all, status_t result);
89 			void				_NotifyLocked(bool all, status_t result);
90 
91 protected:
92 			typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
93 
94 			const void*			fObject;
95 			const char*			fObjectType;
96 
97 			spinlock			fLock;
98 			EntryList			fEntries;
99 			int32				fEntriesCount;
100 
101 			ConditionVariable*	fNext;
102 
103 			friend struct ConditionVariableEntry;
104 			friend struct ConditionVariableHashDefinition;
105 };
106 
107 
108 inline void
109 ConditionVariable::NotifyOne(status_t result)
110 {
111 	_Notify(false, result);
112 }
113 
114 
115 inline void
116 ConditionVariable::NotifyAll(status_t result)
117 {
118 	_Notify(true, result);
119 }
120 
121 
122 extern "C" {
123 #endif	// __cplusplus
124 
125 extern void condition_variable_init();
126 
127 #ifdef __cplusplus
128 }	// extern "C"
129 #endif
130 
131 #endif	/* _KERNEL_CONDITION_VARIABLE_H */
132