Bug 774388 - Patch 9: Introduce NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION - r=mattwoodrow

This commit is contained in:
Benoit Jacob 2014-07-03 14:53:31 -04:00
parent a88b8b44ad
commit 9a085aa41f
6 changed files with 102 additions and 31 deletions

View File

@ -17,6 +17,7 @@
#include "nsCOMPtr.h" // for nsCOMPtr #include "nsCOMPtr.h" // for nsCOMPtr
#include "nsHashKeys.h" // for nsUint64HashKey #include "nsHashKeys.h" // for nsUint64HashKey
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING #include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class nsIObserver; class nsIObserver;
@ -29,7 +30,8 @@ struct FrameMetrics;
class CompositorChild MOZ_FINAL : public PCompositorChild class CompositorChild MOZ_FINAL : public PCompositorChild
{ {
NS_INLINE_DECL_REFCOUNTING(CompositorChild) NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorChild)
public: public:
CompositorChild(ClientLayerManager *aLayerManager); CompositorChild(ClientLayerManager *aLayerManager);

View File

@ -103,7 +103,7 @@ void ReleaseImageBridgeParentSingleton();
class CompositorThreadHolder MOZ_FINAL class CompositorThreadHolder MOZ_FINAL
{ {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorThreadHolder) NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder)
public: public:
CompositorThreadHolder() CompositorThreadHolder()
@ -138,13 +138,10 @@ private:
static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder; static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder;
static bool sFinishedCompositorShutDown = false; static bool sFinishedCompositorShutDown = false;
static MessageLoop* sMainLoop = nullptr;
/* static */ Thread* /* static */ Thread*
CompositorThreadHolder::CreateCompositorThread() CompositorThreadHolder::CreateCompositorThread()
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
sMainLoop = MessageLoop::current();
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!"); MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
@ -321,20 +318,11 @@ CompositorParent::RecvWillStop()
return true; return true;
} }
void DeferredDeleteCompositorParentOnMainThread(CompositorParent* aNowReadyToDie) void CompositorParent::DeferredDestroy()
{
MOZ_ASSERT(NS_IsMainThread());
aNowReadyToDie->mCompositorThreadHolder = nullptr;
aNowReadyToDie->Release();
}
static void DeferredDeleteCompositorParentOnIOThread(CompositorParent* aToBeDeletedOnMainThread)
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(sMainLoop); mCompositorThreadHolder = nullptr;
sMainLoop->PostTask(FROM_HERE, Release();
NewRunnableFunction(&DeferredDeleteCompositorParentOnMainThread,
aToBeDeletedOnMainThread));
} }
bool bool
@ -346,10 +334,9 @@ CompositorParent::RecvStop()
// this thread. // this thread.
// We must keep the compositor parent alive untill the code handling message // We must keep the compositor parent alive untill the code handling message
// reception is finished on this thread. // reception is finished on this thread.
this->AddRef(); // Corresponds to DeferredDeleteCompositorParentOnMainThread's Release this->AddRef(); // Corresponds to DeferredDestroy's Release
MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(&DeferredDeleteCompositorParentOnIOThread, NewRunnableMethod(this,&CompositorParent::DeferredDestroy));
this));
return true; return true;
} }
@ -1129,7 +1116,7 @@ class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent,
{ {
friend class CompositorParent; friend class CompositorParent;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent) NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CrossProcessCompositorParent)
public: public:
CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess) CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess)
: mTransport(aTransport) : mTransport(aTransport)
@ -1201,7 +1188,7 @@ private:
// Child side's process Id. // Child side's process Id.
base::ProcessId mChildProcessId; base::ProcessId mChildProcessId;
const nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder; nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
}; };
void void
@ -1463,12 +1450,8 @@ CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLay
void void
CrossProcessCompositorParent::DeferredDestroy() CrossProcessCompositorParent::DeferredDestroy()
{ {
CrossProcessCompositorParent* self; mCompositorThreadHolder = nullptr;
mSelfRef.forget(&self); mSelfRef = nullptr;
MOZ_ASSERT(sMainLoop);
sMainLoop->PostTask(FROM_HERE,
NewRunnableMethod(self, &CrossProcessCompositorParent::Release));
} }
CrossProcessCompositorParent::~CrossProcessCompositorParent() CrossProcessCompositorParent::~CrossProcessCompositorParent()

View File

@ -33,6 +33,7 @@
#include "nsAutoPtr.h" // for nsRefPtr #include "nsAutoPtr.h" // for nsRefPtr
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "nsSize.h" // for nsIntSize #include "nsSize.h" // for nsIntSize
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class CancelableTask; class CancelableTask;
class MessageLoop; class MessageLoop;
@ -68,7 +69,7 @@ class CompositorThreadHolder;
class CompositorParent : public PCompositorParent, class CompositorParent : public PCompositorParent,
public ShadowLayersManager public ShadowLayersManager
{ {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent) NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent)
public: public:
CompositorParent(nsIWidget* aWidget, CompositorParent(nsIWidget* aWidget,
@ -244,6 +245,8 @@ protected:
// Protected destructor, to discourage deletion outside of Release(): // Protected destructor, to discourage deletion outside of Release():
virtual ~CompositorParent(); virtual ~CompositorParent();
void DeferredDestroy();
virtual PLayerTransactionParent* virtual PLayerTransactionParent*
AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints, AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
const uint64_t& aId, const uint64_t& aId,
@ -314,8 +317,6 @@ protected:
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder; nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
friend void DeferredDeleteCompositorParentOnMainThread(CompositorParent* aNowReadyToDie);
}; };
} // layers } // layers

View File

@ -17,6 +17,7 @@
#include "mozilla/layers/PImageBridgeChild.h" #include "mozilla/layers/PImageBridgeChild.h"
#include "nsDebug.h" // for NS_RUNTIMEABORT #include "nsDebug.h" // for NS_RUNTIMEABORT
#include "nsRegion.h" // for nsIntRegion #include "nsRegion.h" // for nsIntRegion
class MessageLoop; class MessageLoop;
struct nsIntPoint; struct nsIntPoint;
struct nsIntRect; struct nsIntRect;

View File

@ -0,0 +1,83 @@
/* 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 THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#define THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#include "MainThreadUtils.h"
#include "base/message_loop.h"
#include "base/task.h"
namespace mozilla {
namespace layers {
inline MessageLoop* GetMainLoopAssertingMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
return MessageLoop::current();
}
inline MessageLoop* GetMainLoop()
{
static MessageLoop* sMainLoop = GetMainLoopAssertingMainThread();
return sMainLoop;
}
struct HelperForMainThreadDestruction
{
HelperForMainThreadDestruction()
{
MOZ_ASSERT(NS_IsMainThread());
GetMainLoop();
}
~HelperForMainThreadDestruction()
{
MOZ_ASSERT(NS_IsMainThread());
}
};
} // namespace layers
} // namespace mozilla
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(_class) \
public: \
NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
nsrefcnt count = ++mRefCnt; \
NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
return (nsrefcnt) count; \
} \
static void DestroyToBeCalledOnMainThread(_class* ptr) { \
MOZ_ASSERT(NS_IsMainThread()); \
NS_LOG_RELEASE(ptr, 0, #_class); \
delete ptr; \
} \
NS_METHOD_(MozExternalRefCountType) Release(void) { \
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
nsrefcnt count = --mRefCnt; \
if (count == 0) { \
if (NS_IsMainThread()) { \
NS_LOG_RELEASE(this, 0, #_class); \
delete this; \
} else { \
/* no NS_LOG_RELEASE here, will be in the runnable */ \
MessageLoop *l = ::mozilla::layers::GetMainLoop(); \
l->PostTask(FROM_HERE, \
NewRunnableFunction(&DestroyToBeCalledOnMainThread, \
this)); \
} \
} else { \
NS_LOG_RELEASE(this, count, #_class); \
} \
return count; \
} \
protected: \
::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
private: \
::mozilla::layers::HelperForMainThreadDestruction mHelperForMainThreadDestruction; \
public:
#endif

View File

@ -27,6 +27,7 @@ EXPORTS += [
'ipc/CompositorChild.h', 'ipc/CompositorChild.h',
'ipc/CompositorParent.h', 'ipc/CompositorParent.h',
'ipc/ShadowLayersManager.h', 'ipc/ShadowLayersManager.h',
'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h',
'Layers.h', 'Layers.h',
'LayerScope.h', 'LayerScope.h',
'LayersLogging.h', 'LayersLogging.h',