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