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 "mozilla/Monitor.h" 11 # include "mozilla/RefPtr.h" 12 # include "mozilla/StaticPtr.h" 13 # include "nsCOMPtr.h" 14 # include "nsIAsyncShutdown.h" 15 # include "nsIThread.h" 16 # include "nsTHashSet.h" 17 18 namespace mozilla { 19 20 class MediaDecoder; 21 22 // The MediaShutdownManager manages shutting down the MediaDecoder 23 // infrastructure in response to an xpcom-shutdown notification. 24 // This happens when Gecko is shutting down in the middle of operation. 25 // This is tricky, as there are a number of moving parts that must 26 // be shutdown in a particular order. The MediaShutdownManager 27 // encapsulates all these dependencies to ensure that no shutdown 28 // order dependencies leak out of the MediaDecoder stack. 29 // The MediaShutdownManager is a singleton. 30 // 31 // The MediaShutdownManager ensures that the MediaDecoder stack 32 // is shutdown before exiting xpcom-shutdown stage by registering 33 // itself with nsIAsyncShutdownService to receive notification 34 // when the stage of shutdown has started and then calls Shutdown() 35 // on every MediaDecoder. Shutdown will not proceed until all 36 // MediaDecoders finish shutdown and MediaShutdownManager unregisters 37 // itself from the async shutdown service. 38 // 39 // Note that calling the Unregister() functions may result in the singleton 40 // being deleted, so don't store references to the singleton, always use the 41 // singleton by derefing the referenced returned by 42 // MediaShutdownManager::Instance(), which ensures that the singleton is 43 // created when needed. 44 // i.e. like this: 45 // MediaShutdownManager::Instance()::Unregister(someDecoder); 46 // MediaShutdownManager::Instance()::Register(someOtherDecoder); 47 // Not like this: 48 // MediaShutdownManager& instance = MediaShutdownManager::Instance(); 49 // instance.Unregister(someDecoder); // Warning! May delete instance! 50 // instance.Register(someOtherDecoder); // BAD! instance may be dangling! 51 class MediaShutdownManager : public nsIAsyncShutdownBlocker { 52 public: 53 NS_DECL_ISUPPORTS 54 NS_DECL_NSIASYNCSHUTDOWNBLOCKER 55 56 static void InitStatics(); 57 58 // The MediaShutdownManager is a singleton, access its instance with 59 // this accessor. 60 static MediaShutdownManager& Instance(); 61 62 // Notifies the MediaShutdownManager that it needs to track the shutdown 63 // of this MediaDecoder. 64 nsresult Register(MediaDecoder* aDecoder); 65 66 // Notifies the MediaShutdownManager that a MediaDecoder that it was 67 // tracking has shutdown, and it no longer needs to be shutdown in the 68 // xpcom-shutdown listener. 69 void Unregister(MediaDecoder* aDecoder); 70 71 private: 72 enum InitPhase { 73 NotInited, 74 InitSucceeded, 75 InitFailed, 76 XPCOMShutdownStarted, 77 XPCOMShutdownEnded 78 }; 79 80 static InitPhase sInitPhase; 81 82 MediaShutdownManager(); 83 virtual ~MediaShutdownManager(); 84 void RemoveBlocker(); 85 86 static StaticRefPtr<MediaShutdownManager> sInstance; 87 88 // References to the MediaDecoder. The decoders unregister themselves 89 // in their Shutdown() method, so we'll drop the reference naturally when 90 // we're shutting down (in the non xpcom-shutdown case). 91 nsTHashSet<RefPtr<MediaDecoder>> mDecoders; 92 }; 93 94 } // namespace mozilla 95 96 #endif 97