diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 087d12774603..7e683eacdb98 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -14,7 +14,6 @@ #include "MediaTrackConstraints.h" #include "MediaTrackGraphImpl.h" #include "MediaTrackListener.h" -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "VideoStreamTrack.h" #include "VideoUtils.h" #include "mozilla/Base64.h" @@ -303,7 +302,7 @@ class SourceListener : public SupportsWeakPtr { typedef MozPromise, true> SourceListenerPromise; - NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION( + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( SourceListener) SourceListener(); @@ -1946,9 +1945,10 @@ RefPtr MediaManager::EnumerateRawDevices( // Need to ask permission to retrieve list of all devices; // notify frontend observer and wait for callback notification to post task. const char16_t* const type = - (aVideoInputType != MediaSourceEnum::Camera) ? u"audio" - : (aAudioInputType != MediaSourceEnum::Microphone) ? u"video" - : u"all"; + (aVideoInputType != MediaSourceEnum::Camera) + ? u"audio" + : (aAudioInputType != MediaSourceEnum::Microphone) ? u"video" + : u"all"; nsCOMPtr obs = services::GetObserverService(); obs->NotifyObservers(static_cast(task), "getUserMedia:ask-device-permission", type); diff --git a/gfx/layers/ipc/CompositorBridgeChild.h b/gfx/layers/ipc/CompositorBridgeChild.h index 8e1f9fde187a..005fe65250bd 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.h +++ b/gfx/layers/ipc/CompositorBridgeChild.h @@ -21,7 +21,6 @@ #include "nsHashKeys.h" // for nsUint64HashKey #include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING #include "nsIWeakReferenceUtils.h" -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include diff --git a/gfx/layers/ipc/CompositorThread.h b/gfx/layers/ipc/CompositorThread.h index 09f73eafdcb4..2dea93e9d04e 100644 --- a/gfx/layers/ipc/CompositorThread.h +++ b/gfx/layers/ipc/CompositorThread.h @@ -8,7 +8,6 @@ #include "nsISupportsImpl.h" #include "nsIThread.h" -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" class nsISerialEventTarget; class nsIThread; @@ -17,7 +16,7 @@ namespace mozilla { namespace layers { class CompositorThreadHolder final { - NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION( + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( CompositorThreadHolder) public: diff --git a/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h b/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h deleted file mode 100644 index 78c05f1363f8..000000000000 --- a/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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 "nsISupportsImpl.h" -#include "MainThreadUtils.h" -#include "nsThreadUtils.h" - -#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION( \ - _class) \ - private: \ - void DeleteOnMainThread() { \ - if (NS_IsMainThread()) { \ - delete this; \ - return; \ - } \ - NS_DispatchToMainThread(NewNonOwningRunnableMethod( \ - #_class "::DeleteOnMainThread", this, &_class::DeleteOnMainThread)); \ - } \ - \ - NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DESTROY(_class, \ - DeleteOnMainThread()) - -#endif diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index a9486ad9823e..f2c206f9a860 100755 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -32,7 +32,6 @@ EXPORTS += [ "ImageLayers.h", "ImageTypes.h", "IMFYCbCrImage.h", - "ipc/ThreadSafeRefcountingWithMainThreadDestruction.h", "Layers.h", "LayerScope.h", "LayerSorter.h", diff --git a/gfx/vr/VRThread.h b/gfx/vr/VRThread.h index 1aabd1bdec51..4d210a35aa85 100644 --- a/gfx/vr/VRThread.h +++ b/gfx/vr/VRThread.h @@ -7,7 +7,7 @@ #ifndef GFX_VR_THREAD_H #define GFX_VR_THREAD_H -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" +#include "nsISupportsImpl.h" #include "base/thread.h" // for Thread namespace mozilla { diff --git a/gfx/vr/ipc/VRManagerChild.h b/gfx/vr/ipc/VRManagerChild.h index 14cf2fbaac13..b650d80cec13 100644 --- a/gfx/vr/ipc/VRManagerChild.h +++ b/gfx/vr/ipc/VRManagerChild.h @@ -7,13 +7,13 @@ #ifndef MOZILLA_GFX_VR_VRMANAGERCHILD_H #define MOZILLA_GFX_VR_VRMANAGERCHILD_H +#include "nsISupportsImpl.h" #include "mozilla/Attributes.h" #include "mozilla/dom/WindowBinding.h" // For FrameRequestCallback #include "mozilla/dom/WebXRBinding.h" #include "mozilla/dom/XRFrame.h" #include "mozilla/gfx/PVRManagerChild.h" -#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" +#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator #include "mozilla/layers/LayersTypes.h" // for LayersBackend diff --git a/gfx/webrender_bindings/RenderThread.h b/gfx/webrender_bindings/RenderThread.h index ee79aaa440c0..633b13174b71 100644 --- a/gfx/webrender_bindings/RenderThread.h +++ b/gfx/webrender_bindings/RenderThread.h @@ -13,7 +13,6 @@ #include "base/message_loop.h" #include "GLTypes.h" // for GLenum #include "nsISupportsImpl.h" -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "mozilla/gfx/Point.h" #include "mozilla/MozPromise.h" #include "mozilla/DataMutex.h" @@ -131,8 +130,7 @@ class RendererEvent { /// singleton but in some places we pretend it's not). Hopefully we can evolve /// this in a way that keeps the door open to removing the singleton bits. class RenderThread final { - NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION( - RenderThread) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(RenderThread) public: /// Can be called from any thread. diff --git a/widget/windows/WinCompositorWindowThread.h b/widget/windows/WinCompositorWindowThread.h index 06848086ecb7..c1462711ce9e 100644 --- a/widget/windows/WinCompositorWindowThread.h +++ b/widget/windows/WinCompositorWindowThread.h @@ -9,7 +9,6 @@ #include "base/thread.h" #include "base/message_loop.h" -#include "ThreadSafeRefcountingWithMainThreadDestruction.h" namespace mozilla { @@ -27,7 +26,7 @@ struct WinCompositorWnds { }; class WinCompositorWindowThread final { - NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION( + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( WinCompositorWindowThread) public: diff --git a/xpcom/base/nsISupportsImpl.cpp b/xpcom/base/nsISupportsImpl.cpp index e2a4ee3f59f9..c282ec14dbcd 100644 --- a/xpcom/base/nsISupportsImpl.cpp +++ b/xpcom/base/nsISupportsImpl.cpp @@ -7,9 +7,10 @@ #include "nsISupportsImpl.h" #include "mozilla/Assertions.h" -#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED +#ifndef XPCOM_GLUE_AVOID_NSPR +# include "nsPrintfCString.h" # include "nsThreadUtils.h" -#endif // MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED +#endif using namespace mozilla; @@ -32,7 +33,8 @@ nsresult NS_FASTCALL NS_TableDrivenQI(void* aThis, REFNSIID aIID, return NS_ERROR_NO_INTERFACE; } -#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED +#ifndef XPCOM_GLUE_AVOID_NSPR +# ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED nsAutoOwningThread::nsAutoOwningThread() : mThread(PR_GetCurrentThread()) {} void nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const { @@ -67,4 +69,76 @@ bool nsAutoOwningEventTarget::IsCurrentThread() const { return mTarget->IsOnCurrentThread(); } +# endif + +namespace mozilla::detail { +class ProxyDeleteVoidRunnable final : public CancelableRunnable { + public: + ProxyDeleteVoidRunnable(const char* aName, void* aPtr, + DeleteVoidFunction* aDeleteFunc) + : CancelableRunnable(aName), mPtr(aPtr), mDeleteFunc(aDeleteFunc) {} + + NS_IMETHOD Run() override { + if (mPtr) { + mDeleteFunc(mPtr); + mPtr = nullptr; + } + return NS_OK; + } + + // Mimics the behaviour in `ProxyRelease`, freeing the resource when + // cancelled. + nsresult Cancel() override { return Run(); } + +# ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY + NS_IMETHOD GetName(nsACString& aName) override { + if (mName) { + aName.Append(mName); + } else { + aName.AssignLiteral("ProxyDeleteVoidRunnable"); + } + return NS_OK; + } +# endif + + private: + ~ProxyDeleteVoidRunnable() { + if (mPtr) { +# ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY + NS_WARNING( + nsPrintfCString( + "ProxyDeleteVoidRunnable for '%s' never run, leaking!", mName) + .get()); +# else + NS_WARNING("ProxyDeleteVoidRunnable never run, leaking!"); +# endif + } + } + + void* mPtr; + DeleteVoidFunction* mDeleteFunc; +}; + +void ProxyDeleteVoid(const char* aName, nsISerialEventTarget* aTarget, + void* aPtr, DeleteVoidFunction* aDeleteFunc) { + MOZ_ASSERT(aName); + MOZ_ASSERT(aPtr); + MOZ_ASSERT(aDeleteFunc); + if (!aTarget) { + NS_WARNING(nsPrintfCString("no target for '%s', leaking!", aName).get()); + return; + } + + if (aTarget->IsOnCurrentThread()) { + aDeleteFunc(aPtr); + return; + } + nsresult rv = aTarget->Dispatch( + MakeAndAddRef(aName, aPtr, aDeleteFunc), + NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING(nsPrintfCString("failed to post '%s', leaking!", aName).get()); + } +} +} // namespace mozilla::detail #endif diff --git a/xpcom/base/nsISupportsImpl.h b/xpcom/base/nsISupportsImpl.h index bc0f588a7905..83c44f8a180c 100644 --- a/xpcom/base/nsISupportsImpl.h +++ b/xpcom/base/nsISupportsImpl.h @@ -735,6 +735,62 @@ class ThreadSafeAutoRefCnt { NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING_WITH_DESTROY( \ _class, delete (this), __VA_ARGS__) +#if !defined(XPCOM_GLUE_AVOID_NSPR) +class nsISerialEventTarget; +namespace mozilla { +// Forward-declare `GetMainThreadSerialEventTarget`, as `nsISupportsImpl.h` +// cannot include `nsThreadUtils.h`. +nsISerialEventTarget* GetMainThreadSerialEventTarget(); + +namespace detail { +using DeleteVoidFunction = void(void*); +void ProxyDeleteVoid(const char* aRunnableName, + nsISerialEventTarget* aEventTarget, void* aSelf, + DeleteVoidFunction* aDeleteFunc); +} // namespace detail +} // namespace mozilla + +/** + * Helper for _WITH_DELETE_ON_EVENT_TARGET threadsafe refcounting macros which + * provides an implementation of `_destroy` + */ +# define NS_PROXY_DELETE_TO_EVENT_TARGET(_class, _target) \ + ::mozilla::detail::ProxyDeleteVoid( \ + "ProxyDelete " #_class, _target, this, \ + [](void* self) { delete static_cast<_class*>(self); }) + +/** + * Use this macro to declare and implement the AddRef & Release methods for a + * given non-XPCOM _class in a threadsafe manner, ensuring the + * destructor runs on a specific nsISerialEventTarget. + * + * DOES NOT DO REFCOUNT STABILIZATION! + * + * @param _class The name of the class implementing the method + * @param _target nsISerialEventTarget to run the class's destructor on + * @param optional override Mark the AddRef & Release methods as overrides + */ +# define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET( \ + _class, _target, ...) \ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DESTROY( \ + _class, NS_PROXY_DELETE_TO_EVENT_TARGET(_class, _target), __VA_ARGS__) + +/** + * Use this macro to declare and implement the AddRef & Release methods for a + * given non-XPCOM _class in a threadsafe manner, ensuring the + * destructor runs on the main thread. + * + * DOES NOT DO REFCOUNT STABILIZATION! + * + * @param _class The name of the class implementing the method + * @param optional override Mark the AddRef & Release methods as overrides + */ +# define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( \ + _class, ...) \ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET( \ + _class, ::mozilla::GetMainThreadSerialEventTarget(), __VA_ARGS__) +#endif + /** * Use this macro in interface classes that you want to be able to reference * using RefPtr, but don't want to provide a refcounting implemenation. The