gecko-dev/xpcom/threads/CondVar.h

140 строки
3.6 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 "mozilla/BlockingResourceBase.h"
#include "mozilla/PlatformConditionVariable.h"
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#if defined(MOZILLA_INTERNAL_API) && !defined(DEBUG)
# include "mozilla/ProfilerThreadSleep.h"
#endif // defined( MOZILLA_INTERNAL_API) && !defined(DEBUG)
namespace mozilla {
/**
* Similarly to OffTheBooksMutex, OffTheBooksCondvar is identical to CondVar,
* except that OffTheBooksCondVar doesn't include leak checking. Sometimes
* you want to intentionally "leak" a CondVar until shutdown; in these cases,
* OffTheBooksCondVar is for you.
*/
class OffTheBooksCondVar : BlockingResourceBase {
public:
/**
* OffTheBooksCondVar
*
* 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()
**/
OffTheBooksCondVar(OffTheBooksMutex& aLock, const char* aName)
: BlockingResourceBase(aName, eCondVar), mLock(&aLock) {}
/**
* ~OffTheBooksCondVar
* Clean up after this OffTheBooksCondVar, but NOT its associated Mutex.
**/
~OffTheBooksCondVar() = default;
/**
* Wait
* @see prcvar.h
**/
#ifndef DEBUG
void Wait() {
# ifdef MOZILLA_INTERNAL_API
AUTO_PROFILER_THREAD_SLEEP;
# endif // MOZILLA_INTERNAL_API
mImpl.wait(*mLock);
}
CVStatus Wait(TimeDuration aDuration) {
# ifdef MOZILLA_INTERNAL_API
AUTO_PROFILER_THREAD_SLEEP;
# endif // MOZILLA_INTERNAL_API
return mImpl.wait_for(*mLock, aDuration);
}
#else
// NOTE: debug impl is in BlockingResourceBase.cpp
void Wait();
CVStatus Wait(TimeDuration aDuration);
#endif
/**
* Notify
* @see prcvar.h
**/
void Notify() { mImpl.notify_one(); }
/**
* NotifyAll
* @see prcvar.h
**/
void NotifyAll() { mImpl.notify_all(); }
#ifdef DEBUG
/**
* AssertCurrentThreadOwnsMutex
* @see Mutex::AssertCurrentThreadOwns
**/
void AssertCurrentThreadOwnsMutex() const ASSERT_CAPABILITY(mLock) {
mLock->AssertCurrentThreadOwns();
}
/**
* AssertNotCurrentThreadOwnsMutex
* @see Mutex::AssertNotCurrentThreadOwns
**/
void AssertNotCurrentThreadOwnsMutex() const ASSERT_CAPABILITY(!mLock) {
mLock->AssertNotCurrentThreadOwns();
}
#else
void AssertCurrentThreadOwnsMutex() const ASSERT_CAPABILITY(mLock) {}
void AssertNotCurrentThreadOwnsMutex() const ASSERT_CAPABILITY(!mLock) {}
#endif // ifdef DEBUG
private:
OffTheBooksCondVar();
OffTheBooksCondVar(const OffTheBooksCondVar&) = delete;
OffTheBooksCondVar& operator=(const OffTheBooksCondVar&) = delete;
OffTheBooksMutex* mLock;
detail::ConditionVariableImpl mImpl;
};
/**
* CondVar
* Vanilla condition variable. Please don't use this unless you have a
* compelling reason --- Monitor provides a simpler API.
*/
class CondVar : public OffTheBooksCondVar {
public:
CondVar(OffTheBooksMutex& aLock, const char* aName)
: OffTheBooksCondVar(aLock, aName) {
MOZ_COUNT_CTOR(CondVar);
}
MOZ_COUNTED_DTOR(CondVar)
private:
CondVar();
CondVar(const CondVar&);
CondVar& operator=(const CondVar&);
};
} // namespace mozilla
#endif // ifndef mozilla_CondVar_h