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