1 /* 2 * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _KERNEL_CONDITION_VARIABLE_H 6 #define _KERNEL_CONDITION_VARIABLE_H 7 8 9 #include <OS.h> 10 11 #include <debug.h> 12 13 #ifdef __cplusplus 14 15 #include <util/OpenHashTable.h> 16 17 18 class PrivateConditionVariable; 19 20 21 struct PrivateConditionVariableEntry { 22 public: 23 #if KDEBUG 24 inline PrivateConditionVariableEntry() 25 : fVariable(NULL) 26 { 27 } 28 29 inline ~PrivateConditionVariableEntry() 30 { 31 if (fVariable != NULL) { 32 panic("Destroying condition variable entry %p, but it's still " 33 "attached to variable %p\n", this, fVariable); 34 } 35 } 36 #endif 37 38 inline PrivateConditionVariable* Variable() const 39 { return fVariable; } 40 41 inline PrivateConditionVariableEntry* ThreadNext() const 42 { return fThreadNext; } 43 inline PrivateConditionVariableEntry* ThreadPrevious() const 44 { return fThreadPrevious; } 45 46 class Private; 47 48 protected: 49 bool Add(const void* object, 50 PrivateConditionVariableEntry* threadNext); 51 status_t Wait(uint32 flags); 52 status_t Wait(const void* object, uint32 flags); 53 54 private: 55 void _Remove(); 56 57 protected: 58 PrivateConditionVariableEntry* fVariableNext; 59 PrivateConditionVariable* fVariable; 60 struct thread* fThread; 61 uint32 fFlags; 62 status_t fResult; 63 64 PrivateConditionVariableEntry* fThreadPrevious; 65 PrivateConditionVariableEntry* fThreadNext; 66 67 friend class PrivateConditionVariable; 68 friend class Private; 69 }; 70 71 72 class PrivateConditionVariable 73 : protected HashTableLink<PrivateConditionVariable> { 74 public: 75 static void ListAll(); 76 void Dump(); 77 78 protected: 79 void Publish(const void* object, 80 const char* objectType); 81 void Unpublish(bool threadsLocked); 82 void Notify(bool all, bool threadsLocked); 83 84 private: 85 void _Notify(bool all, status_t result); 86 87 protected: 88 const void* fObject; 89 const char* fObjectType; 90 PrivateConditionVariableEntry* fEntries; 91 92 friend class PrivateConditionVariableEntry; 93 friend class ConditionVariableHashDefinition; 94 }; 95 96 97 template<typename Type = void> 98 class ConditionVariable : private PrivateConditionVariable { 99 public: 100 inline void Publish(const Type* object, 101 const char* objectType); 102 103 inline void Unpublish(bool threadsLocked = false); 104 inline void NotifyOne(bool threadsLocked = false); 105 inline void NotifyAll(bool threadsLocked = false); 106 }; 107 108 109 template<typename Type = void> 110 class ConditionVariableEntry : public PrivateConditionVariableEntry { 111 public: 112 inline bool Add(const Type* object, 113 PrivateConditionVariableEntry* threadNext 114 = NULL); 115 inline status_t Wait(uint32 flags = 0); 116 inline status_t Wait(const Type* object, uint32 flags = 0); 117 }; 118 119 120 template<typename Type> 121 inline void 122 ConditionVariable<Type>::Publish(const Type* object, const char* objectType) 123 { 124 PrivateConditionVariable::Publish(object, objectType); 125 } 126 127 128 template<typename Type> 129 inline void 130 ConditionVariable<Type>::Unpublish(bool threadsLocked) 131 { 132 PrivateConditionVariable::Unpublish(threadsLocked); 133 } 134 135 136 template<typename Type> 137 inline void 138 ConditionVariable<Type>::NotifyOne(bool threadsLocked) 139 { 140 PrivateConditionVariable::Notify(false, threadsLocked); 141 } 142 143 144 template<typename Type> 145 inline void 146 ConditionVariable<Type>::NotifyAll(bool threadsLocked) 147 { 148 PrivateConditionVariable::Notify(true, threadsLocked); 149 } 150 151 152 template<typename Type> 153 inline bool 154 ConditionVariableEntry<Type>::Add(const Type* object, 155 PrivateConditionVariableEntry* threadNext) 156 { 157 return PrivateConditionVariableEntry::Add(object, threadNext); 158 } 159 160 161 template<typename Type> 162 inline status_t 163 ConditionVariableEntry<Type>::Wait(uint32 flags) 164 { 165 return PrivateConditionVariableEntry::Wait(flags); 166 } 167 168 169 template<typename Type> 170 inline status_t 171 ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags) 172 { 173 return PrivateConditionVariableEntry::Wait(object, flags); 174 } 175 176 177 extern "C" { 178 #endif // __cplusplus 179 180 struct thread; 181 182 extern status_t condition_variable_interrupt_thread(struct thread* thread); 183 184 extern void condition_variable_init(); 185 186 #ifdef __cplusplus 187 } // extern "C" 188 #endif 189 190 #endif /* _KERNEL_CONDITION_VARIABLE_H */ 191