1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et ft=cpp : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MediaUtils.h"
8 #include "mozilla/Services.h"
10 namespace mozilla::media
{
12 nsCOMPtr
<nsIAsyncShutdownClient
> GetShutdownBarrier() {
13 nsCOMPtr
<nsIAsyncShutdownService
> svc
= services::GetAsyncShutdownService();
15 // We can fail to get the shutdown service if we're already shutting down.
19 nsCOMPtr
<nsIAsyncShutdownClient
> barrier
;
20 nsresult rv
= svc
->GetProfileBeforeChange(getter_AddRefs(barrier
));
22 // We are probably in a content process. We need to do cleanup at
23 // XPCOM shutdown in leakchecking builds.
24 rv
= svc
->GetXpcomWillShutdown(getter_AddRefs(barrier
));
26 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv
));
27 MOZ_RELEASE_ASSERT(barrier
);
31 nsCOMPtr
<nsIAsyncShutdownClient
> MustGetShutdownBarrier() {
32 nsCOMPtr
<nsIAsyncShutdownClient
> barrier
= GetShutdownBarrier();
33 MOZ_RELEASE_ASSERT(barrier
);
37 NS_IMPL_ISUPPORTS(ShutdownBlocker
, nsIAsyncShutdownBlocker
)
40 class MediaEventBlocker
: public ShutdownBlocker
{
42 explicit MediaEventBlocker(nsString aName
)
43 : ShutdownBlocker(std::move(aName
)) {}
46 BlockShutdown(nsIAsyncShutdownClient
* aProfileBeforeChange
) override
{
47 mShutdownEvent
.Notify();
51 MediaEventSource
<void>& ShutdownEvent() { return mShutdownEvent
; }
54 MediaEventProducer
<void> mShutdownEvent
;
57 class RefCountedTicket
{
58 RefPtr
<MediaEventBlocker
> mBlocker
;
59 MediaEventForwarder
<void> mShutdownEventForwarder
;
62 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedTicket
)
65 : mShutdownEventForwarder(GetMainThreadSerialEventTarget()) {}
67 void AddBlocker(const nsString
& aName
, const nsString
& aFileName
,
69 MOZ_ASSERT(NS_IsMainThread());
70 MOZ_ASSERT(!mBlocker
);
71 mBlocker
= MakeAndAddRef
<MediaEventBlocker
>(aName
);
72 mShutdownEventForwarder
.Forward(mBlocker
->ShutdownEvent());
73 GetShutdownBarrier()->AddBlocker(mBlocker
.get(), aFileName
, aLineNr
, aName
);
76 MediaEventSource
<void>& ShutdownEvent() { return mShutdownEventForwarder
; }
79 virtual ~RefCountedTicket() {
80 MOZ_ASSERT(NS_IsMainThread());
82 GetShutdownBarrier()->RemoveBlocker(mBlocker
.get());
83 mShutdownEventForwarder
.DisconnectAll();
87 class ShutdownBlockingTicketImpl
: public ShutdownBlockingTicket
{
89 RefPtr
<RefCountedTicket
> mTicket
;
92 ShutdownBlockingTicketImpl(nsString aName
, nsString aFileName
,
94 : mTicket(MakeAndAddRef
<RefCountedTicket
>()) {
95 aName
.AppendPrintf(" - %p", this);
96 NS_DispatchToMainThread(NS_NewRunnableFunction(
97 __func__
, [ticket
= mTicket
, name
= std::move(aName
),
98 fileName
= std::move(aFileName
), lineNr
= aLineNr
] {
99 ticket
->AddBlocker(name
, fileName
, lineNr
);
103 ~ShutdownBlockingTicketImpl() {
104 NS_ReleaseOnMainThread(__func__
, mTicket
.forget(), true);
107 MediaEventSource
<void>& ShutdownEvent() override
{
108 return mTicket
->ShutdownEvent();
113 UniquePtr
<ShutdownBlockingTicket
> ShutdownBlockingTicket::Create(
114 nsString aName
, nsString aFileName
, int32_t aLineNr
) {
115 return WrapUnique(new ShutdownBlockingTicketImpl(
116 std::move(aName
), std::move(aFileName
), aLineNr
));
119 } // namespace mozilla::media