Bug 774388 - Patch 12: make ImageBridgeParent 's refcounting implementation automatically defer destruction to the main thread - r=nical

This commit is contained in:
Benoit Jacob 2014-07-04 14:04:12 -04:00
parent aa0a4dc9b8
commit 1d691a18f6
2 changed files with 32 additions and 14 deletions

View File

@ -8,6 +8,10 @@
#include "mozilla/RefPtr.h"
#include "mozilla/NullPtr.h"
#include "mozilla/Likely.h"
#include "MainThreadUtils.h"
#include "base/message_loop.h"
#include "base/task.h"
namespace mozilla {
@ -18,10 +22,21 @@ class AtomicRefCountedWithFinalize
AtomicRefCountedWithFinalize()
: mRecycleCallback(nullptr)
, mRefCount(0)
, mMessageLoopToPostDestructionTo(nullptr)
{}
~AtomicRefCountedWithFinalize() {}
void SetMessageLoopToPostDestructionTo(MessageLoop* l) {
MOZ_ASSERT(NS_IsMainThread());
mMessageLoopToPostDestructionTo = l;
}
static void DestroyToBeCalledOnMainThread(T* ptr) {
MOZ_ASSERT(NS_IsMainThread());
delete ptr;
}
public:
void AddRef() {
MOZ_ASSERT(mRefCount >= 0);
@ -43,7 +58,17 @@ class AtomicRefCountedWithFinalize
#endif
T* derived = static_cast<T*>(this);
derived->Finalize();
if (MOZ_LIKELY(!mMessageLoopToPostDestructionTo)) {
delete derived;
} else {
if (MOZ_LIKELY(NS_IsMainThread())) {
delete derived;
} else {
mMessageLoopToPostDestructionTo->PostTask(
FROM_HERE,
NewRunnableFunction(&DestroyToBeCalledOnMainThread, derived));
}
}
} else if (1 == currCount && recycleCallback) {
T* derived = static_cast<T*>(this);
recycleCallback(derived, mClosure);
@ -71,6 +96,7 @@ private:
RecycleCallback mRecycleCallback;
void *mClosure;
Atomic<int> mRefCount;
MessageLoop *mMessageLoopToPostDestructionTo;
};
}

View File

@ -54,12 +54,15 @@ ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
, mChildProcessId(aChildProcessId)
{
MOZ_ASSERT(NS_IsMainThread());
sMainLoop = MessageLoop::current();
// top-level actors must be destroyed on the main thread.
SetMessageLoopToPostDestructionTo(sMainLoop);
// creates the map only if it has not been created already, so it is safe
// with several bridges
CompositableMap::Create();
sImageBridges[aChildProcessId] = this;
sMainLoop = MessageLoop::current();
}
ImageBridgeParent::~ImageBridgeParent()
@ -274,21 +277,10 @@ MessageLoop * ImageBridgeParent::GetMessageLoop() const {
return mMessageLoop;
}
static void
DeferredReleaseImageBridgeParentOnMainThread(ImageBridgeParent* aDyingImageBridgeParent)
{
aDyingImageBridgeParent->Release();
}
void
ImageBridgeParent::DeferredDestroy()
{
ImageBridgeParent* self;
mSelfRef.forget(&self);
sMainLoop->PostTask(
FROM_HERE,
NewRunnableFunction(&DeferredReleaseImageBridgeParentOnMainThread, this));
mSelfRef = nullptr;
}
ImageBridgeParent*