зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1339677. Part 3 - add some sanity checks. r=gerald
MozReview-Commit-ID: AXq9KQGKGni --HG-- extra : rebase_source : e78a7339920605ee66e407e184582f80588646f8 extra : source : 53227d5296decb587aaf214c8f33875cdb2a6f2d
This commit is contained in:
Родитель
46381af26b
Коммит
fd3595243f
|
@ -19,6 +19,16 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
|
||||
#define PROMISE_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef PROMISE_DEBUG
|
||||
#define PROMISE_ASSERT MOZ_RELEASE_ASSERT
|
||||
#else
|
||||
#define PROMISE_ASSERT(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
extern LazyLogModule gMozPromiseLog;
|
||||
|
@ -120,6 +130,8 @@ template<typename T> class MozPromiseRequestHolder;
|
|||
template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
|
||||
class MozPromise : public MozPromiseRefcountable
|
||||
{
|
||||
static const uint32_t sMagic = 0xcecace11;
|
||||
|
||||
public:
|
||||
typedef ResolveValueT ResolveValueType;
|
||||
typedef RejectValueT RejectValueType;
|
||||
|
@ -299,6 +311,7 @@ protected:
|
|||
class ThenValueBase : public Request
|
||||
{
|
||||
friend class MozPromise;
|
||||
static const uint32_t sMagic = 0xfadece11;
|
||||
|
||||
public:
|
||||
class ResolveOrRejectRunnable : public Runnable
|
||||
|
@ -338,8 +351,17 @@ protected:
|
|||
, mCallSite(aCallSite)
|
||||
{ }
|
||||
|
||||
#ifdef PROMISE_DEBUG
|
||||
~ThenValueBase()
|
||||
{
|
||||
mMagic1 = 0;
|
||||
mMagic2 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void AssertIsDead() override
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
|
||||
// We want to assert that this ThenValues is dead - that is to say, that
|
||||
// there are no consumers waiting for the result. In the case of a normal
|
||||
// ThenValue, we check that it has been disconnected, which is the way
|
||||
|
@ -356,6 +378,7 @@ protected:
|
|||
|
||||
void Dispatch(MozPromise *aPromise)
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
|
||||
aPromise->mMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(!aPromise->IsPending());
|
||||
|
||||
|
@ -389,6 +412,7 @@ protected:
|
|||
|
||||
void DoResolveOrReject(const ResolveOrRejectValue& aValue)
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsCurrentThreadIn());
|
||||
Request::mComplete = true;
|
||||
if (Request::mDisconnected) {
|
||||
|
@ -411,7 +435,13 @@ protected:
|
|||
}
|
||||
|
||||
RefPtr<AbstractThread> mResponseTarget; // May be released on any thread.
|
||||
#ifdef PROMISE_DEBUG
|
||||
uint32_t mMagic1 = sMagic;
|
||||
#endif
|
||||
RefPtr<Private> mCompletionPromise;
|
||||
#ifdef PROMISE_DEBUG
|
||||
uint32_t mMagic2 = sMagic;
|
||||
#endif
|
||||
const char* mCallSite;
|
||||
};
|
||||
|
||||
|
@ -661,6 +691,7 @@ public:
|
|||
void ThenInternal(AbstractThread* aResponseThread, ThenValueBase* aThenValue,
|
||||
const char* aCallSite)
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic);
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(aResponseThread->IsDispatchReliable());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
|
||||
|
@ -814,6 +845,7 @@ public:
|
|||
// AssertIsDead() only.
|
||||
void AssertIsDead()
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic);
|
||||
MutexAutoLock lock(mMutex);
|
||||
for (auto&& then : mThenValues) {
|
||||
then->AssertIsDead();
|
||||
|
@ -868,13 +900,27 @@ protected:
|
|||
MOZ_ASSERT(mThenValues.IsEmpty());
|
||||
MOZ_ASSERT(mChainedPromises.IsEmpty());
|
||||
}
|
||||
#ifdef PROMISE_DEBUG
|
||||
mMagic1 = 0;
|
||||
mMagic2 = 0;
|
||||
mMagic3 = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
const char* mCreationSite; // For logging
|
||||
Mutex mMutex;
|
||||
ResolveOrRejectValue mValue;
|
||||
#ifdef PROMISE_DEBUG
|
||||
uint32_t mMagic1 = sMagic;
|
||||
#endif
|
||||
nsTArray<RefPtr<ThenValueBase>> mThenValues;
|
||||
#ifdef PROMISE_DEBUG
|
||||
uint32_t mMagic2 = sMagic;
|
||||
#endif
|
||||
nsTArray<RefPtr<Private>> mChainedPromises;
|
||||
#ifdef PROMISE_DEBUG
|
||||
uint32_t mMagic3 = sMagic;
|
||||
#endif
|
||||
bool mHaveRequest;
|
||||
const bool mIsCompletionPromise;
|
||||
};
|
||||
|
@ -890,6 +936,7 @@ public:
|
|||
template<typename ResolveValueT_>
|
||||
void Resolve(ResolveValueT_&& aResolveValue, const char* aResolveSite)
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic);
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(IsPending());
|
||||
PROMISE_LOG("%s resolving MozPromise (%p created at %s)", aResolveSite, this, mCreationSite);
|
||||
|
@ -900,6 +947,7 @@ public:
|
|||
template<typename RejectValueT_>
|
||||
void Reject(RejectValueT_&& aRejectValue, const char* aRejectSite)
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic);
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(IsPending());
|
||||
PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite, this, mCreationSite);
|
||||
|
@ -910,6 +958,7 @@ public:
|
|||
template<typename ResolveOrRejectValue_>
|
||||
void ResolveOrReject(ResolveOrRejectValue_&& aValue, const char* aSite)
|
||||
{
|
||||
PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic);
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(IsPending());
|
||||
PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)", aSite, this, mCreationSite);
|
||||
|
@ -1339,6 +1388,8 @@ InvokeAsync(AbstractThread* aTarget, const char* aCallerName,
|
|||
}
|
||||
|
||||
#undef PROMISE_LOG
|
||||
#undef PROMISE_ASSERT
|
||||
#undef PROMISE_DEBUG
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче