content/media/MediaShutdownManager.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/MediaShutdownManager.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,149 @@
     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 +#include "MediaShutdownManager.h"
    1.11 +#include "nsContentUtils.h"
    1.12 +#include "mozilla/StaticPtr.h"
    1.13 +#include "MediaDecoder.h"
    1.14 +#include "SharedThreadPool.h"
    1.15 +#include "prlog.h"
    1.16 +
    1.17 +namespace mozilla {
    1.18 +
    1.19 +#ifdef PR_LOGGING
    1.20 +extern PRLogModuleInfo* gMediaDecoderLog;
    1.21 +#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
    1.22 +#else
    1.23 +#define DECODER_LOG(type, msg)
    1.24 +#endif
    1.25 +
    1.26 +NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIObserver)
    1.27 +
    1.28 +MediaShutdownManager::MediaShutdownManager()
    1.29 +  : mIsObservingShutdown(false),
    1.30 +    mIsDoingXPCOMShutDown(false)
    1.31 +{
    1.32 +  MOZ_ASSERT(NS_IsMainThread());
    1.33 +  MOZ_COUNT_CTOR(MediaShutdownManager);
    1.34 +}
    1.35 +
    1.36 +MediaShutdownManager::~MediaShutdownManager()
    1.37 +{
    1.38 +  MOZ_ASSERT(NS_IsMainThread());
    1.39 +  MOZ_COUNT_DTOR(MediaShutdownManager);
    1.40 +}
    1.41 +
    1.42 +// Note that we don't use ClearOnShutdown() on this StaticRefPtr, as that
    1.43 +// may interfere with our shutdown listener.
    1.44 +StaticRefPtr<MediaShutdownManager> MediaShutdownManager::sInstance;
    1.45 +
    1.46 +MediaShutdownManager&
    1.47 +MediaShutdownManager::Instance()
    1.48 +{
    1.49 +  MOZ_ASSERT(NS_IsMainThread());
    1.50 +  if (!sInstance) {
    1.51 +    sInstance = new MediaShutdownManager();
    1.52 +  }
    1.53 +  return *sInstance;
    1.54 +}
    1.55 +
    1.56 +void
    1.57 +MediaShutdownManager::EnsureCorrectShutdownObserverState()
    1.58 +{
    1.59 +  MOZ_ASSERT(!mIsDoingXPCOMShutDown);
    1.60 +  bool needShutdownObserver = mDecoders.Count() > 0;
    1.61 +  if (needShutdownObserver != mIsObservingShutdown) {
    1.62 +    mIsObservingShutdown = needShutdownObserver;
    1.63 +    if (mIsObservingShutdown) {
    1.64 +      nsContentUtils::RegisterShutdownObserver(this);
    1.65 +    } else {
    1.66 +      nsContentUtils::UnregisterShutdownObserver(this);
    1.67 +      // Clear our singleton reference. This will probably delete
    1.68 +      // this instance, so don't deref |this| clearing sInstance.
    1.69 +      sInstance = nullptr;
    1.70 +    }
    1.71 +  }
    1.72 +}
    1.73 +
    1.74 +void
    1.75 +MediaShutdownManager::Register(MediaDecoder* aDecoder)
    1.76 +{
    1.77 +  MOZ_ASSERT(NS_IsMainThread());
    1.78 +  // Don't call Register() after you've Unregistered() all the decoders,
    1.79 +  // that's not going to work.
    1.80 +  MOZ_ASSERT(!mDecoders.Contains(aDecoder));
    1.81 +  mDecoders.PutEntry(aDecoder);
    1.82 +  MOZ_ASSERT(mDecoders.Contains(aDecoder));
    1.83 +  MOZ_ASSERT(mDecoders.Count() > 0);
    1.84 +  EnsureCorrectShutdownObserverState();
    1.85 +}
    1.86 +
    1.87 +void
    1.88 +MediaShutdownManager::Unregister(MediaDecoder* aDecoder)
    1.89 +{
    1.90 +  MOZ_ASSERT(NS_IsMainThread());
    1.91 +  MOZ_ASSERT(mDecoders.Contains(aDecoder));
    1.92 +  if (!mIsDoingXPCOMShutDown) {
    1.93 +    mDecoders.RemoveEntry(aDecoder);
    1.94 +    EnsureCorrectShutdownObserverState();
    1.95 +  }
    1.96 +}
    1.97 +
    1.98 +NS_IMETHODIMP
    1.99 +MediaShutdownManager::Observe(nsISupports *aSubjet,
   1.100 +                              const char *aTopic,
   1.101 +                              const char16_t *someData)
   1.102 +{
   1.103 +  MOZ_ASSERT(NS_IsMainThread());
   1.104 +  if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
   1.105 +    Shutdown();
   1.106 +  }
   1.107 +  return NS_OK;
   1.108 +}
   1.109 +
   1.110 +static PLDHashOperator
   1.111 +ShutdownMediaDecoder(nsRefPtrHashKey<MediaDecoder>* aEntry, void*)
   1.112 +{
   1.113 +  aEntry->GetKey()->Shutdown();
   1.114 +  return PL_DHASH_REMOVE;
   1.115 +}
   1.116 +
   1.117 +void
   1.118 +MediaShutdownManager::Shutdown()
   1.119 +{
   1.120 +  MOZ_ASSERT(NS_IsMainThread());
   1.121 +  MOZ_ASSERT(sInstance);
   1.122 +
   1.123 +  DECODER_LOG(PR_LOG_DEBUG, ("MediaShutdownManager::Shutdown() start..."));
   1.124 +
   1.125 +  // Mark that we're shutting down, so that Unregister(*) calls don't remove
   1.126 +  // hashtable entries. If Unregsiter(*) was to remove from the hash table,
   1.127 +  // the iterations over the hashtables below would be disrupted.
   1.128 +  mIsDoingXPCOMShutDown = true;
   1.129 +
   1.130 +  // Iterate over the decoders and shut them down, and remove them from the
   1.131 +  // hashtable.
   1.132 +  mDecoders.EnumerateEntries(ShutdownMediaDecoder, nullptr);
   1.133 +
   1.134 +  // Ensure all media shared thread pools are shutdown. This joins with all
   1.135 +  // threads in the state machine thread pool, the decoder thread pool, and
   1.136 +  // any others.
   1.137 +  SharedThreadPool::SpinUntilShutdown();
   1.138 +
   1.139 +  // Remove the MediaShutdownManager instance from the shutdown observer
   1.140 +  // list.
   1.141 +  nsContentUtils::UnregisterShutdownObserver(this);
   1.142 +
   1.143 +  // Clear the singleton instance. The only remaining reference should be the
   1.144 +  // reference that the observer service used to call us with. The
   1.145 +  // MediaShutdownManager will be deleted once the observer service cleans
   1.146 +  // up after it finishes its notifications.
   1.147 +  sInstance = nullptr;
   1.148 +
   1.149 +  DECODER_LOG(PR_LOG_DEBUG, ("MediaShutdownManager::Shutdown() end."));
   1.150 +}
   1.151 +
   1.152 +} // namespace mozilla

mercurial