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 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 void NotifyOne(status_t result = B_OK); 62 inline void NotifyAll(status_t result = B_OK); 63 64 static void NotifyOne(const void* object, status_t result); 65 static void 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 81 private: 82 static void _Notify(const void* object, bool all, status_t result); 83 void _Notify(bool all, status_t result); 84 void _NotifyLocked(bool all, status_t result); 85 86 protected: 87 typedef DoublyLinkedList<ConditionVariableEntry> EntryList; 88 89 const void* fObject; 90 const char* fObjectType; 91 92 spinlock fLock; 93 EntryList fEntries; 94 int32 fEntriesCount; 95 96 ConditionVariable* fNext; 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 105 inline void 106 ConditionVariable::NotifyOne(status_t result) 107 { 108 _Notify(false, result); 109 } 110 111 112 inline void 113 ConditionVariable::NotifyAll(status_t result) 114 { 115 _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