mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
Bug 1392235, part 2 - Fix AutoReferenceChainGuard to never set/unset state when it breaks a reference chain. r=longsonr
MozReview-Commit-ID: I4y8eNGU0Er
This commit is contained in:
parent
37ee4415b8
commit
45e8436173
@ -82,22 +82,23 @@ public:
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mFrame(aFrame)
|
||||
, mFrameInUse(aFrameInUse)
|
||||
, mChainCounter(aChainCounter)
|
||||
, mMaxChainLength(aMaxChainLength)
|
||||
, mBrokeReference(false)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
MOZ_ASSERT(aFrame && aFrameInUse && aChainCounter);
|
||||
MOZ_ASSERT(aMaxChainLength > 0);
|
||||
MOZ_ASSERT(*aChainCounter == noChain ||
|
||||
(*aChainCounter >= 0 && *aChainCounter < aMaxChainLength));
|
||||
|
||||
if (*aChainCounter == noChain) {
|
||||
// Initialize - we start at aMaxChainLength and decrement towards zero.
|
||||
*aChainCounter = aMaxChainLength;
|
||||
}
|
||||
mChainCounter = aChainCounter;
|
||||
}
|
||||
|
||||
~AutoReferenceChainGuard() {
|
||||
if (mBrokeReference) {
|
||||
// We didn't change mFrameInUse or mChainCounter
|
||||
return;
|
||||
}
|
||||
|
||||
*mFrameInUse = false;
|
||||
|
||||
// If we fail this assert then there were more destructor calls than
|
||||
@ -121,22 +122,30 @@ public:
|
||||
*/
|
||||
MOZ_MUST_USE bool Reference() {
|
||||
if (MOZ_UNLIKELY(*mFrameInUse)) {
|
||||
mBrokeReference = true;
|
||||
ReportErrorToConsole();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*mChainCounter == noChain) {
|
||||
// Initialize - we start at aMaxChainLength and decrement towards zero.
|
||||
*mChainCounter = mMaxChainLength;
|
||||
} else {
|
||||
// If we fail this assertion then either a consumer failed to break a
|
||||
// reference loop/chain, or else they called Reference() more than once
|
||||
MOZ_ASSERT(*mChainCounter >= 0);
|
||||
|
||||
if (MOZ_UNLIKELY(*mChainCounter < 1)) {
|
||||
mBrokeReference = true;
|
||||
ReportErrorToConsole();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We only set these once we know we're returing true.
|
||||
*mFrameInUse = true;
|
||||
|
||||
// If we fail this assertion then either a consumer failed to break a
|
||||
// reference loop/chain, or else they called Reference() more than once
|
||||
MOZ_ASSERT(*mChainCounter >= 0);
|
||||
|
||||
(*mChainCounter)--;
|
||||
|
||||
if (MOZ_UNLIKELY(*mChainCounter < 0)) {
|
||||
ReportErrorToConsole();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -157,6 +166,7 @@ private:
|
||||
bool* mFrameInUse;
|
||||
int16_t* mChainCounter;
|
||||
const int16_t mMaxChainLength;
|
||||
bool mBrokeReference;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user