Fri, 16 Jan 2015 04:50:19 +0100
Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32
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"
8 #include "nsContentUtils.h"
9 #include "mozilla/StaticPtr.h"
10 #include "MediaDecoder.h"
11 #include "SharedThreadPool.h"
12 #include "prlog.h"
14 namespace mozilla {
16 #ifdef PR_LOGGING
17 extern PRLogModuleInfo* gMediaDecoderLog;
18 #define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
19 #else
20 #define DECODER_LOG(type, msg)
21 #endif
23 NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIObserver)
25 MediaShutdownManager::MediaShutdownManager()
26 : mIsObservingShutdown(false),
27 mIsDoingXPCOMShutDown(false)
28 {
29 MOZ_ASSERT(NS_IsMainThread());
30 MOZ_COUNT_CTOR(MediaShutdownManager);
31 }
33 MediaShutdownManager::~MediaShutdownManager()
34 {
35 MOZ_ASSERT(NS_IsMainThread());
36 MOZ_COUNT_DTOR(MediaShutdownManager);
37 }
39 // Note that we don't use ClearOnShutdown() on this StaticRefPtr, as that
40 // may interfere with our shutdown listener.
41 StaticRefPtr<MediaShutdownManager> MediaShutdownManager::sInstance;
43 MediaShutdownManager&
44 MediaShutdownManager::Instance()
45 {
46 MOZ_ASSERT(NS_IsMainThread());
47 if (!sInstance) {
48 sInstance = new MediaShutdownManager();
49 }
50 return *sInstance;
51 }
53 void
54 MediaShutdownManager::EnsureCorrectShutdownObserverState()
55 {
56 MOZ_ASSERT(!mIsDoingXPCOMShutDown);
57 bool needShutdownObserver = mDecoders.Count() > 0;
58 if (needShutdownObserver != mIsObservingShutdown) {
59 mIsObservingShutdown = needShutdownObserver;
60 if (mIsObservingShutdown) {
61 nsContentUtils::RegisterShutdownObserver(this);
62 } else {
63 nsContentUtils::UnregisterShutdownObserver(this);
64 // Clear our singleton reference. This will probably delete
65 // this instance, so don't deref |this| clearing sInstance.
66 sInstance = nullptr;
67 }
68 }
69 }
71 void
72 MediaShutdownManager::Register(MediaDecoder* aDecoder)
73 {
74 MOZ_ASSERT(NS_IsMainThread());
75 // Don't call Register() after you've Unregistered() all the decoders,
76 // that's not going to work.
77 MOZ_ASSERT(!mDecoders.Contains(aDecoder));
78 mDecoders.PutEntry(aDecoder);
79 MOZ_ASSERT(mDecoders.Contains(aDecoder));
80 MOZ_ASSERT(mDecoders.Count() > 0);
81 EnsureCorrectShutdownObserverState();
82 }
84 void
85 MediaShutdownManager::Unregister(MediaDecoder* aDecoder)
86 {
87 MOZ_ASSERT(NS_IsMainThread());
88 MOZ_ASSERT(mDecoders.Contains(aDecoder));
89 if (!mIsDoingXPCOMShutDown) {
90 mDecoders.RemoveEntry(aDecoder);
91 EnsureCorrectShutdownObserverState();
92 }
93 }
95 NS_IMETHODIMP
96 MediaShutdownManager::Observe(nsISupports *aSubjet,
97 const char *aTopic,
98 const char16_t *someData)
99 {
100 MOZ_ASSERT(NS_IsMainThread());
101 if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
102 Shutdown();
103 }
104 return NS_OK;
105 }
107 static PLDHashOperator
108 ShutdownMediaDecoder(nsRefPtrHashKey<MediaDecoder>* aEntry, void*)
109 {
110 aEntry->GetKey()->Shutdown();
111 return PL_DHASH_REMOVE;
112 }
114 void
115 MediaShutdownManager::Shutdown()
116 {
117 MOZ_ASSERT(NS_IsMainThread());
118 MOZ_ASSERT(sInstance);
120 DECODER_LOG(PR_LOG_DEBUG, ("MediaShutdownManager::Shutdown() start..."));
122 // Mark that we're shutting down, so that Unregister(*) calls don't remove
123 // hashtable entries. If Unregsiter(*) was to remove from the hash table,
124 // the iterations over the hashtables below would be disrupted.
125 mIsDoingXPCOMShutDown = true;
127 // Iterate over the decoders and shut them down, and remove them from the
128 // hashtable.
129 mDecoders.EnumerateEntries(ShutdownMediaDecoder, nullptr);
131 // Ensure all media shared thread pools are shutdown. This joins with all
132 // threads in the state machine thread pool, the decoder thread pool, and
133 // any others.
134 SharedThreadPool::SpinUntilShutdown();
136 // Remove the MediaShutdownManager instance from the shutdown observer
137 // list.
138 nsContentUtils::UnregisterShutdownObserver(this);
140 // Clear the singleton instance. The only remaining reference should be the
141 // reference that the observer service used to call us with. The
142 // MediaShutdownManager will be deleted once the observer service cleans
143 // up after it finishes its notifications.
144 sInstance = nullptr;
146 DECODER_LOG(PR_LOG_DEBUG, ("MediaShutdownManager::Shutdown() end."));
147 }
149 } // namespace mozilla