1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/MediaShutdownManager.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,105 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#if !defined(MediaShutdownManager_h_) 1.11 +#define MediaShutdownManager_h_ 1.12 + 1.13 +#include "nsIObserver.h" 1.14 +#include "mozilla/Monitor.h" 1.15 +#include "mozilla/RefPtr.h" 1.16 +#include "mozilla/StaticPtr.h" 1.17 +#include "nsIThread.h" 1.18 +#include "nsCOMPtr.h" 1.19 +#include "nsTHashtable.h" 1.20 +#include "nsHashKeys.h" 1.21 + 1.22 +namespace mozilla { 1.23 + 1.24 +class MediaDecoder; 1.25 +class StateMachineThread; 1.26 + 1.27 +// The MediaShutdownManager manages shutting down the MediaDecoder 1.28 +// infrastructure in response to an xpcom-shutdown notification. This happens 1.29 +// when Gecko is shutting down in the middle of operation. This is tricky, as 1.30 +// there are a number of moving parts that must be shutdown in a particular 1.31 +// order. Additionally the xpcom-shutdown observer *must* block until all 1.32 +// threads are shutdown, which is tricky since we have a number of threads 1.33 +// here and their shutdown is asynchronous. We can't have each element of 1.34 +// our pipeline listening for xpcom-shutdown, as if each observer blocks 1.35 +// waiting for its threads to shutdown it will block other xpcom-shutdown 1.36 +// notifications from firing, and shutdown of one part of the media pipeline 1.37 +// (say the State Machine thread) may depend another part to be shutdown 1.38 +// first (the MediaDecoder threads). The MediaShutdownManager encapsulates 1.39 +// all these dependencies, and provides a single xpcom-shutdown listener 1.40 +// for the MediaDecoder infrastructure, to ensure that no shutdown order 1.41 +// dependencies leak out of the MediaDecoder stack. The MediaShutdownManager 1.42 +// is a singleton. 1.43 +// 1.44 +// The MediaShutdownManager ensures that the MediaDecoder stack is shutdown 1.45 +// before returning from its xpcom-shutdown observer by keeping track of all 1.46 +// the active MediaDecoders, and upon xpcom-shutdown calling Shutdown() on 1.47 +// every MediaDecoder and then spinning the main thread event loop until all 1.48 +// SharedThreadPools have shutdown. Once the SharedThreadPools are shutdown, 1.49 +// all the state machines and their threads have been shutdown, the 1.50 +// xpcom-shutdown observer returns. 1.51 +// 1.52 +// Note that calling the Unregister() functions may result in the singleton 1.53 +// being deleted, so don't store references to the singleton, always use the 1.54 +// singleton by derefing the referenced returned by 1.55 +// MediaShutdownManager::Instance(), which ensures that the singleton is 1.56 +// created when needed. 1.57 +// i.e. like this: 1.58 +// MediaShutdownManager::Instance()::Unregister(someDecoder); 1.59 +// MediaShutdownManager::Instance()::Register(someOtherDecoder); 1.60 +// Not like this: 1.61 +// MediaShutdownManager& instance = MediaShutdownManager::Instance(); 1.62 +// instance.Unregister(someDecoder); // Warning! May delete instance! 1.63 +// instance.Register(someOtherDecoder); // BAD! instance may be dangling! 1.64 +class MediaShutdownManager : public nsIObserver { 1.65 +public: 1.66 + NS_DECL_ISUPPORTS 1.67 + NS_DECL_NSIOBSERVER 1.68 + 1.69 + // The MediaShutdownManager is a singleton, access its instance with 1.70 + // this accessor. 1.71 + static MediaShutdownManager& Instance(); 1.72 + 1.73 + // Notifies the MediaShutdownManager that it needs to track the shutdown 1.74 + // of this MediaDecoder. 1.75 + void Register(MediaDecoder* aDecoder); 1.76 + 1.77 + // Notifies the MediaShutdownManager that a MediaDecoder that it was 1.78 + // tracking has shutdown, and it no longer needs to be shutdown in the 1.79 + // xpcom-shutdown listener. 1.80 + void Unregister(MediaDecoder* aDecoder); 1.81 + 1.82 +private: 1.83 + 1.84 + MediaShutdownManager(); 1.85 + virtual ~MediaShutdownManager(); 1.86 + 1.87 + void Shutdown(); 1.88 + 1.89 + // Ensures we have a shutdown listener if we need one, and removes the 1.90 + // listener and destroys the singleton if we don't. 1.91 + void EnsureCorrectShutdownObserverState(); 1.92 + 1.93 + static StaticRefPtr<MediaShutdownManager> sInstance; 1.94 + 1.95 + // References to the MediaDecoder. The decoders unregister themselves 1.96 + // in their Shutdown() method, so we'll drop the reference naturally when 1.97 + // we're shutting down (in the non xpcom-shutdown case). 1.98 + nsTHashtable<nsRefPtrHashKey<MediaDecoder>> mDecoders; 1.99 + 1.100 + // True if we have an XPCOM shutdown observer. 1.101 + bool mIsObservingShutdown; 1.102 + 1.103 + bool mIsDoingXPCOMShutDown; 1.104 +}; 1.105 + 1.106 +} // namespace mozilla 1.107 + 1.108 +#endif