diff --git a/gfx/layers/ipc/CompositorChild.h b/gfx/layers/ipc/CompositorChild.h index f59e21a316c..50af4d4f071 100644 --- a/gfx/layers/ipc/CompositorChild.h +++ b/gfx/layers/ipc/CompositorChild.h @@ -17,6 +17,7 @@ #include "nsCOMPtr.h" // for nsCOMPtr #include "nsHashKeys.h" // for nsUint64HashKey #include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING +#include "ThreadSafeRefcountingWithMainThreadDestruction.h" class nsIObserver; @@ -29,7 +30,8 @@ struct FrameMetrics; class CompositorChild MOZ_FINAL : public PCompositorChild { - NS_INLINE_DECL_REFCOUNTING(CompositorChild) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorChild) + public: CompositorChild(ClientLayerManager *aLayerManager); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 27033bd2b75..eaf960d03af 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -103,7 +103,7 @@ void ReleaseImageBridgeParentSingleton(); class CompositorThreadHolder MOZ_FINAL { - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorThreadHolder) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder) public: CompositorThreadHolder() @@ -138,13 +138,10 @@ private: static StaticRefPtr sCompositorThreadHolder; static bool sFinishedCompositorShutDown = false; -static MessageLoop* sMainLoop = nullptr; - /* static */ Thread* CompositorThreadHolder::CreateCompositorThread() { MOZ_ASSERT(NS_IsMainThread()); - sMainLoop = MessageLoop::current(); MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!"); @@ -321,20 +318,11 @@ CompositorParent::RecvWillStop() return true; } -void DeferredDeleteCompositorParentOnMainThread(CompositorParent* aNowReadyToDie) -{ - MOZ_ASSERT(NS_IsMainThread()); - aNowReadyToDie->mCompositorThreadHolder = nullptr; - aNowReadyToDie->Release(); -} - -static void DeferredDeleteCompositorParentOnIOThread(CompositorParent* aToBeDeletedOnMainThread) +void CompositorParent::DeferredDestroy() { MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(sMainLoop); - sMainLoop->PostTask(FROM_HERE, - NewRunnableFunction(&DeferredDeleteCompositorParentOnMainThread, - aToBeDeletedOnMainThread)); + mCompositorThreadHolder = nullptr; + Release(); } bool @@ -346,10 +334,9 @@ CompositorParent::RecvStop() // this thread. // We must keep the compositor parent alive untill the code handling message // 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, - NewRunnableFunction(&DeferredDeleteCompositorParentOnIOThread, - this)); + NewRunnableMethod(this,&CompositorParent::DeferredDestroy)); return true; } @@ -1129,7 +1116,7 @@ class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent, { friend class CompositorParent; - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CrossProcessCompositorParent) public: CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess) : mTransport(aTransport) @@ -1201,7 +1188,7 @@ private: // Child side's process Id. base::ProcessId mChildProcessId; - const nsRefPtr mCompositorThreadHolder; + nsRefPtr mCompositorThreadHolder; }; void @@ -1463,12 +1450,8 @@ CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLay void CrossProcessCompositorParent::DeferredDestroy() { - CrossProcessCompositorParent* self; - mSelfRef.forget(&self); - - MOZ_ASSERT(sMainLoop); - sMainLoop->PostTask(FROM_HERE, - NewRunnableMethod(self, &CrossProcessCompositorParent::Release)); + mCompositorThreadHolder = nullptr; + mSelfRef = nullptr; } CrossProcessCompositorParent::~CrossProcessCompositorParent() diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 203c3d43552..728cc242387 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -33,6 +33,7 @@ #include "nsAutoPtr.h" // for nsRefPtr #include "nsISupportsImpl.h" #include "nsSize.h" // for nsIntSize +#include "ThreadSafeRefcountingWithMainThreadDestruction.h" class CancelableTask; class MessageLoop; @@ -68,7 +69,7 @@ class CompositorThreadHolder; class CompositorParent : public PCompositorParent, public ShadowLayersManager { - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent) public: CompositorParent(nsIWidget* aWidget, @@ -244,6 +245,8 @@ protected: // Protected destructor, to discourage deletion outside of Release(): virtual ~CompositorParent(); + void DeferredDestroy(); + virtual PLayerTransactionParent* AllocPLayerTransactionParent(const nsTArray& aBackendHints, const uint64_t& aId, @@ -314,8 +317,6 @@ protected: nsRefPtr mCompositorThreadHolder; DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); - - friend void DeferredDeleteCompositorParentOnMainThread(CompositorParent* aNowReadyToDie); }; } // layers diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index 124c9f773c4..214bd19dfa0 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -17,6 +17,7 @@ #include "mozilla/layers/PImageBridgeChild.h" #include "nsDebug.h" // for NS_RUNTIMEABORT #include "nsRegion.h" // for nsIntRegion + class MessageLoop; struct nsIntPoint; struct nsIntRect; diff --git a/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h b/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h new file mode 100644 index 00000000000..0d5f39235d2 --- /dev/null +++ b/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h @@ -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 \ No newline at end of file diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index eb7123dea67..8d021197ad2 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -27,6 +27,7 @@ EXPORTS += [ 'ipc/CompositorChild.h', 'ipc/CompositorParent.h', 'ipc/ShadowLayersManager.h', + 'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h', 'Layers.h', 'LayerScope.h', 'LayersLogging.h',