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:
JW Wang 2017-02-16 11:43:46 +08:00
Родитель 46381af26b
Коммит fd3595243f
1 изменённых файлов: 51 добавлений и 0 удалений

Просмотреть файл

@ -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