|
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/. */ |
|
6 |
|
7 #if !defined(MediaShutdownManager_h_) |
|
8 #define MediaShutdownManager_h_ |
|
9 |
|
10 #include "nsIObserver.h" |
|
11 #include "mozilla/Monitor.h" |
|
12 #include "mozilla/RefPtr.h" |
|
13 #include "mozilla/StaticPtr.h" |
|
14 #include "nsIThread.h" |
|
15 #include "nsCOMPtr.h" |
|
16 #include "nsTHashtable.h" |
|
17 #include "nsHashKeys.h" |
|
18 |
|
19 namespace mozilla { |
|
20 |
|
21 class MediaDecoder; |
|
22 class StateMachineThread; |
|
23 |
|
24 // The MediaShutdownManager manages shutting down the MediaDecoder |
|
25 // infrastructure in response to an xpcom-shutdown notification. This happens |
|
26 // when Gecko is shutting down in the middle of operation. This is tricky, as |
|
27 // there are a number of moving parts that must be shutdown in a particular |
|
28 // order. Additionally the xpcom-shutdown observer *must* block until all |
|
29 // threads are shutdown, which is tricky since we have a number of threads |
|
30 // here and their shutdown is asynchronous. We can't have each element of |
|
31 // our pipeline listening for xpcom-shutdown, as if each observer blocks |
|
32 // waiting for its threads to shutdown it will block other xpcom-shutdown |
|
33 // notifications from firing, and shutdown of one part of the media pipeline |
|
34 // (say the State Machine thread) may depend another part to be shutdown |
|
35 // first (the MediaDecoder threads). The MediaShutdownManager encapsulates |
|
36 // all these dependencies, and provides a single xpcom-shutdown listener |
|
37 // for the MediaDecoder infrastructure, to ensure that no shutdown order |
|
38 // dependencies leak out of the MediaDecoder stack. The MediaShutdownManager |
|
39 // is a singleton. |
|
40 // |
|
41 // The MediaShutdownManager ensures that the MediaDecoder stack is shutdown |
|
42 // before returning from its xpcom-shutdown observer by keeping track of all |
|
43 // the active MediaDecoders, and upon xpcom-shutdown calling Shutdown() on |
|
44 // every MediaDecoder and then spinning the main thread event loop until all |
|
45 // SharedThreadPools have shutdown. Once the SharedThreadPools are shutdown, |
|
46 // all the state machines and their threads have been shutdown, the |
|
47 // xpcom-shutdown observer returns. |
|
48 // |
|
49 // Note that calling the Unregister() functions may result in the singleton |
|
50 // being deleted, so don't store references to the singleton, always use the |
|
51 // singleton by derefing the referenced returned by |
|
52 // MediaShutdownManager::Instance(), which ensures that the singleton is |
|
53 // created when needed. |
|
54 // i.e. like this: |
|
55 // MediaShutdownManager::Instance()::Unregister(someDecoder); |
|
56 // MediaShutdownManager::Instance()::Register(someOtherDecoder); |
|
57 // Not like this: |
|
58 // MediaShutdownManager& instance = MediaShutdownManager::Instance(); |
|
59 // instance.Unregister(someDecoder); // Warning! May delete instance! |
|
60 // instance.Register(someOtherDecoder); // BAD! instance may be dangling! |
|
61 class MediaShutdownManager : public nsIObserver { |
|
62 public: |
|
63 NS_DECL_ISUPPORTS |
|
64 NS_DECL_NSIOBSERVER |
|
65 |
|
66 // The MediaShutdownManager is a singleton, access its instance with |
|
67 // this accessor. |
|
68 static MediaShutdownManager& Instance(); |
|
69 |
|
70 // Notifies the MediaShutdownManager that it needs to track the shutdown |
|
71 // of this MediaDecoder. |
|
72 void Register(MediaDecoder* aDecoder); |
|
73 |
|
74 // Notifies the MediaShutdownManager that a MediaDecoder that it was |
|
75 // tracking has shutdown, and it no longer needs to be shutdown in the |
|
76 // xpcom-shutdown listener. |
|
77 void Unregister(MediaDecoder* aDecoder); |
|
78 |
|
79 private: |
|
80 |
|
81 MediaShutdownManager(); |
|
82 virtual ~MediaShutdownManager(); |
|
83 |
|
84 void Shutdown(); |
|
85 |
|
86 // Ensures we have a shutdown listener if we need one, and removes the |
|
87 // listener and destroys the singleton if we don't. |
|
88 void EnsureCorrectShutdownObserverState(); |
|
89 |
|
90 static StaticRefPtr<MediaShutdownManager> sInstance; |
|
91 |
|
92 // References to the MediaDecoder. The decoders unregister themselves |
|
93 // in their Shutdown() method, so we'll drop the reference naturally when |
|
94 // we're shutting down (in the non xpcom-shutdown case). |
|
95 nsTHashtable<nsRefPtrHashKey<MediaDecoder>> mDecoders; |
|
96 |
|
97 // True if we have an XPCOM shutdown observer. |
|
98 bool mIsObservingShutdown; |
|
99 |
|
100 bool mIsDoingXPCOMShutDown; |
|
101 }; |
|
102 |
|
103 } // namespace mozilla |
|
104 |
|
105 #endif |