gecko-dev/xpcom/threads/CondVar.h

145 строки
3.2 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_CondVar_h
#define mozilla_CondVar_h
#include "prcvar.h"
#include "mozilla/BlockingResourceBase.h"
#include "mozilla/Mutex.h"
#ifdef MOZILLA_INTERNAL_API
#include "GeckoProfiler.h"
#endif //MOZILLA_INTERNAL_API
namespace mozilla {
/**
* CondVar
* Vanilla condition variable. Please don't use this unless you have a
* compelling reason --- Monitor provides a simpler API.
*/
class CondVar : BlockingResourceBase
{
public:
/**
* CondVar
*
* The CALLER owns |aLock|.
*
* @param aLock A Mutex to associate with this condition variable.
* @param aName A name which can reference this monitor
* @returns If failure, nullptr.
* If success, a valid Monitor* which must be destroyed
* by Monitor::DestroyMonitor()
**/
CondVar(Mutex& aLock, const char* aName)
: BlockingResourceBase(aName, eCondVar)
, mLock(&aLock)
{
MOZ_COUNT_CTOR(CondVar);
// |aLock| must necessarily already be known to the deadlock detector
mCvar = PR_NewCondVar(mLock->mLock);
if (!mCvar) {
MOZ_CRASH("Can't allocate mozilla::CondVar");
}
}
/**
* ~CondVar
* Clean up after this CondVar, but NOT its associated Mutex.
**/
~CondVar()
{
NS_ASSERTION(mCvar && mLock,
"improperly constructed CondVar or double free");
PR_DestroyCondVar(mCvar);
mCvar = 0;
mLock = 0;
MOZ_COUNT_DTOR(CondVar);
}
#ifndef DEBUG
/**
* Wait
* @see prcvar.h
**/
nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
{
#ifdef MOZILLA_INTERNAL_API
GeckoProfilerThreadSleepRAII sleep;
#endif //MOZILLA_INTERNAL_API
// NSPR checks for lock ownership
return PR_WaitCondVar(mCvar, aInterval) == PR_SUCCESS ? NS_OK :
NS_ERROR_FAILURE;
}
#else
nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT);
#endif // ifndef DEBUG
/**
* Notify
* @see prcvar.h
**/
nsresult Notify()
{
// NSPR checks for lock ownership
return PR_NotifyCondVar(mCvar) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
}
/**
* NotifyAll
* @see prcvar.h
**/
nsresult NotifyAll()
{
// NSPR checks for lock ownership
return PR_NotifyAllCondVar(mCvar) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
}
#ifdef DEBUG
/**
* AssertCurrentThreadOwnsMutex
* @see Mutex::AssertCurrentThreadOwns
**/
void AssertCurrentThreadOwnsMutex()
{
mLock->AssertCurrentThreadOwns();
}
/**
* AssertNotCurrentThreadOwnsMutex
* @see Mutex::AssertNotCurrentThreadOwns
**/
void AssertNotCurrentThreadOwnsMutex()
{
mLock->AssertNotCurrentThreadOwns();
}
#else
void AssertCurrentThreadOwnsMutex() {}
void AssertNotCurrentThreadOwnsMutex() {}
#endif // ifdef DEBUG
private:
CondVar();
CondVar(CondVar&);
CondVar& operator=(CondVar&);
Mutex* mLock;
PRCondVar* mCvar;
};
} // namespace mozilla
#endif // ifndef mozilla_CondVar_h