1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_CondVar_h 8 #define mozilla_CondVar_h 9 10 #include "prcvar.h" 11 12 #include "mozilla/BlockingResourceBase.h" 13 #include "mozilla/Mutex.h" 14 15 #ifdef MOZILLA_INTERNAL_API 16 #include "GeckoProfiler.h" 17 #endif //MOZILLA_INTERNAL_API 18 19 namespace mozilla { 20 21 22 /** 23 * CondVar 24 * Vanilla condition variable. Please don't use this unless you have a 25 * compelling reason --- Monitor provides a simpler API. 26 */ 27 class CondVar : BlockingResourceBase 28 { 29 public: 30 /** 31 * CondVar 32 * 33 * The CALLER owns |aLock|. 34 * 35 * @param aLock A Mutex to associate with this condition variable. 36 * @param aName A name which can reference this monitor 37 * @returns If failure, nullptr. 38 * If success, a valid Monitor* which must be destroyed 39 * by Monitor::DestroyMonitor() 40 **/ CondVar(Mutex & aLock,const char * aName)41 CondVar(Mutex& aLock, const char* aName) 42 : BlockingResourceBase(aName, eCondVar) 43 , mLock(&aLock) 44 { 45 MOZ_COUNT_CTOR(CondVar); 46 // |aLock| must necessarily already be known to the deadlock detector 47 mCvar = PR_NewCondVar(mLock->mLock); 48 if (!mCvar) { 49 NS_RUNTIMEABORT("Can't allocate mozilla::CondVar"); 50 } 51 } 52 53 /** 54 * ~CondVar 55 * Clean up after this CondVar, but NOT its associated Mutex. 56 **/ ~CondVar()57 ~CondVar() 58 { 59 NS_ASSERTION(mCvar && mLock, 60 "improperly constructed CondVar or double free"); 61 PR_DestroyCondVar(mCvar); 62 mCvar = 0; 63 mLock = 0; 64 MOZ_COUNT_DTOR(CondVar); 65 } 66 67 #ifndef DEBUG 68 /** 69 * Wait 70 * @see prcvar.h 71 **/ 72 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT) 73 { 74 75 #ifdef MOZILLA_INTERNAL_API 76 GeckoProfilerSleepRAII profiler_sleep; 77 #endif //MOZILLA_INTERNAL_API 78 // NSPR checks for lock ownership 79 return PR_WaitCondVar(mCvar, aInterval) == PR_SUCCESS ? NS_OK : 80 NS_ERROR_FAILURE; 81 } 82 #else 83 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT); 84 #endif // ifndef DEBUG 85 86 /** 87 * Notify 88 * @see prcvar.h 89 **/ Notify()90 nsresult Notify() 91 { 92 // NSPR checks for lock ownership 93 return PR_NotifyCondVar(mCvar) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; 94 } 95 96 /** 97 * NotifyAll 98 * @see prcvar.h 99 **/ NotifyAll()100 nsresult NotifyAll() 101 { 102 // NSPR checks for lock ownership 103 return PR_NotifyAllCondVar(mCvar) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; 104 } 105 106 #ifdef DEBUG 107 /** 108 * AssertCurrentThreadOwnsMutex 109 * @see Mutex::AssertCurrentThreadOwns 110 **/ AssertCurrentThreadOwnsMutex()111 void AssertCurrentThreadOwnsMutex() 112 { 113 mLock->AssertCurrentThreadOwns(); 114 } 115 116 /** 117 * AssertNotCurrentThreadOwnsMutex 118 * @see Mutex::AssertNotCurrentThreadOwns 119 **/ AssertNotCurrentThreadOwnsMutex()120 void AssertNotCurrentThreadOwnsMutex() 121 { 122 mLock->AssertNotCurrentThreadOwns(); 123 } 124 125 #else AssertCurrentThreadOwnsMutex()126 void AssertCurrentThreadOwnsMutex() {} AssertNotCurrentThreadOwnsMutex()127 void AssertNotCurrentThreadOwnsMutex() {} 128 129 #endif // ifdef DEBUG 130 131 private: 132 CondVar(); 133 CondVar(CondVar&); 134 CondVar& operator=(CondVar&); 135 136 Mutex* mLock; 137 PRCondVar* mCvar; 138 }; 139 140 141 } // namespace mozilla 142 143 144 #endif // ifndef mozilla_CondVar_h 145