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, bool threadsLocked, 86 status_t result); 87 88 protected: 89 const void* fObject; 90 const char* fObjectType; 91 PrivateConditionVariableEntry* fEntries; 92 93 friend class PrivateConditionVariableEntry; 94 friend class ConditionVariableHashDefinition; 95 }; 96 97 98 template<typename Type> 99 class ConditionVariable : private PrivateConditionVariable { 100 public: 101 inline void Publish(const Type* object, 102 const char* objectType); 103 104 inline void Unpublish(bool threadsLocked = false); 105 inline void NotifyOne(bool threadsLocked = false); 106 inline void NotifyAll(bool threadsLocked = false); 107 }; 108 109 110 template<typename Type> 111 class ConditionVariableEntry : public PrivateConditionVariableEntry { 112 public: 113 inline bool Add(const Type* object, 114 PrivateConditionVariableEntry* threadNext 115 = NULL); 116 inline status_t Wait(uint32 flags = 0); 117 inline status_t Wait(const Type* object, uint32 flags = 0); 118 }; 119 120 121 template<typename Type> 122 inline void 123 ConditionVariable<Type>::Publish(const Type* object, const char* objectType) 124 { 125 PrivateConditionVariable::Publish(object, objectType); 126 } 127 128 129 template<typename Type> 130 inline void 131 ConditionVariable<Type>::Unpublish(bool threadsLocked) 132 { 133 PrivateConditionVariable::Unpublish(threadsLocked); 134 } 135 136 137 template<typename Type> 138 inline void 139 ConditionVariable<Type>::NotifyOne(bool threadsLocked) 140 { 141 PrivateConditionVariable::Notify(false, threadsLocked); 142 } 143 144 145 template<typename Type> 146 inline void 147 ConditionVariable<Type>::NotifyAll(bool threadsLocked) 148 { 149 PrivateConditionVariable::Notify(true, threadsLocked); 150 } 151 152 153 template<typename Type> 154 inline bool 155 ConditionVariableEntry<Type>::Add(const Type* object, 156 PrivateConditionVariableEntry* threadNext) 157 { 158 return PrivateConditionVariableEntry::Add(object, threadNext); 159 } 160 161 162 template<typename Type> 163 inline status_t 164 ConditionVariableEntry<Type>::Wait(uint32 flags) 165 { 166 return PrivateConditionVariableEntry::Wait(flags); 167 } 168 169 170 template<typename Type> 171 inline status_t 172 ConditionVariableEntry<Type>::Wait(const Type* object, uint32 flags) 173 { 174 return PrivateConditionVariableEntry::Wait(object, flags); 175 } 176 177 178 extern "C" { 179 #endif // __cplusplus 180 181 struct thread; 182 183 extern status_t condition_variable_interrupt_thread(struct thread* thread); 184 185 extern void condition_variable_init(); 186 187 #ifdef __cplusplus 188 } // extern "C" 189 #endif 190 191 #endif /* _KERNEL_CONDITION_VARIABLE_H */ 192