Bug 1708422: part 16) Rename `mozInlineSpellChecker::SpellCheckerTimeSlice` to `mozIn...
[gecko.git] / dom / media / MediaShutdownManager.cpp
blobf2f899bf2ab7a2ee372be546970026287d00afb2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MediaShutdownManager.h"
9 #include "MediaDecoder.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/media/MediaUtils.h"
12 #include "mozilla/Services.h"
13 #include "mozilla/StaticPtr.h"
15 namespace mozilla {
17 #undef LOGW
19 extern LazyLogModule gMediaDecoderLog;
20 #define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
21 #define LOGW(...) NS_WARNING(nsPrintfCString(__VA_ARGS__).get())
23 NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIAsyncShutdownBlocker)
25 MediaShutdownManager::MediaShutdownManager() {
26 MOZ_ASSERT(NS_IsMainThread());
27 MOZ_DIAGNOSTIC_ASSERT(sInitPhase == NotInited);
30 MediaShutdownManager::~MediaShutdownManager() { MOZ_ASSERT(NS_IsMainThread()); }
32 // Note that we don't use ClearOnShutdown() on this StaticRefPtr, as that
33 // may interfere with our shutdown listener.
34 StaticRefPtr<MediaShutdownManager> MediaShutdownManager::sInstance;
36 MediaShutdownManager::InitPhase MediaShutdownManager::sInitPhase =
37 MediaShutdownManager::NotInited;
39 MediaShutdownManager& MediaShutdownManager::Instance() {
40 MOZ_ASSERT(NS_IsMainThread());
41 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
42 if (!sInstance) {
43 MOZ_CRASH_UNSAFE_PRINTF("sInstance is null. sInitPhase=%d",
44 int(sInitPhase));
46 #endif
47 return *sInstance;
50 void MediaShutdownManager::InitStatics() {
51 MOZ_ASSERT(NS_IsMainThread());
52 if (sInitPhase != NotInited) {
53 return;
56 sInstance = new MediaShutdownManager();
57 MOZ_DIAGNOSTIC_ASSERT(sInstance);
59 nsCOMPtr<nsIAsyncShutdownClient> barrier = media::GetShutdownBarrier();
61 if (!barrier) {
62 LOGW("Failed to get barrier, cannot add shutdown blocker!");
63 sInitPhase = InitFailed;
64 return;
67 nsresult rv =
68 barrier->AddBlocker(sInstance, NS_LITERAL_STRING_FROM_CSTRING(__FILE__),
69 __LINE__, u"MediaShutdownManager shutdown"_ns);
70 if (NS_FAILED(rv)) {
71 LOGW("Failed to add shutdown blocker! rv=%x", uint32_t(rv));
72 sInitPhase = InitFailed;
73 return;
75 sInitPhase = InitSucceeded;
78 void MediaShutdownManager::RemoveBlocker() {
79 MOZ_ASSERT(NS_IsMainThread());
80 MOZ_DIAGNOSTIC_ASSERT(sInitPhase == XPCOMShutdownStarted);
81 MOZ_ASSERT(mDecoders.Count() == 0);
82 nsCOMPtr<nsIAsyncShutdownClient> barrier = media::GetShutdownBarrier();
83 // xpcom should still be available because we blocked shutdown by having a
84 // blocker. Until it completely shuts down we should still be able to get
85 // the barrier.
86 MOZ_RELEASE_ASSERT(
87 barrier,
88 "Failed to get shutdown barrier, cannot remove shutdown blocker!");
89 barrier->RemoveBlocker(this);
90 // Clear our singleton reference. This will probably delete
91 // this instance, so don't deref |this| clearing sInstance.
92 sInitPhase = XPCOMShutdownEnded;
93 sInstance = nullptr;
94 DECODER_LOG(LogLevel::Debug, ("MediaShutdownManager::BlockShutdown() end."));
97 nsresult MediaShutdownManager::Register(MediaDecoder* aDecoder) {
98 MOZ_ASSERT(NS_IsMainThread());
99 if (sInitPhase == InitFailed) {
100 return NS_ERROR_NOT_INITIALIZED;
102 if (sInitPhase == XPCOMShutdownStarted) {
103 return NS_ERROR_ABORT;
105 // Don't call Register() after you've Unregistered() all the decoders,
106 // that's not going to work.
107 MOZ_ASSERT(!mDecoders.Contains(aDecoder));
108 mDecoders.Insert(aDecoder);
109 MOZ_ASSERT(mDecoders.Contains(aDecoder));
110 MOZ_ASSERT(mDecoders.Count() > 0);
111 return NS_OK;
114 void MediaShutdownManager::Unregister(MediaDecoder* aDecoder) {
115 MOZ_ASSERT(NS_IsMainThread());
116 if (!mDecoders.EnsureRemoved(aDecoder)) {
117 return;
119 if (sInitPhase == XPCOMShutdownStarted && mDecoders.Count() == 0) {
120 RemoveBlocker();
124 NS_IMETHODIMP
125 MediaShutdownManager::GetName(nsAString& aName) {
126 aName = u"MediaShutdownManager: shutdown"_ns;
127 return NS_OK;
130 NS_IMETHODIMP
131 MediaShutdownManager::GetState(nsIPropertyBag**) { return NS_OK; }
133 NS_IMETHODIMP
134 MediaShutdownManager::BlockShutdown(nsIAsyncShutdownClient*) {
135 MOZ_ASSERT(NS_IsMainThread());
136 MOZ_DIAGNOSTIC_ASSERT(sInitPhase == InitSucceeded);
137 MOZ_DIAGNOSTIC_ASSERT(sInstance);
139 DECODER_LOG(LogLevel::Debug,
140 ("MediaShutdownManager::BlockShutdown() start..."));
142 // Set this flag to ensure no Register() is allowed when Shutdown() begins.
143 sInitPhase = XPCOMShutdownStarted;
145 auto oldCount = mDecoders.Count();
146 if (oldCount == 0) {
147 RemoveBlocker();
148 return NS_OK;
151 // Iterate over the decoders and shut them down.
152 for (const auto& key : mDecoders) {
153 key->NotifyXPCOMShutdown();
154 // Check MediaDecoder::Shutdown doesn't call Unregister() synchronously in
155 // order not to corrupt our hashtable traversal.
156 MOZ_ASSERT(mDecoders.Count() == oldCount);
159 return NS_OK;
162 } // namespace mozilla
164 // avoid redefined macro in unified build
165 #undef LOGW