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