Bug 1411504. P1 - always require MediaCache to have a thread to run Update() loops. draft
authorJW Wang <jwwang@mozilla.com>
Mon, 23 Oct 2017 16:51:17 +0800
changeset 686103 7a643739a149b86924f89817baa3780a2d3c3575
parent 685972 e8db574aec2cd769e10bb18fe926f2e11540a7c4
child 686104 a827191f9e551b405c0ba5ea902c649960f4f1c6
push id86100
push userjwwang@mozilla.com
push dateWed, 25 Oct 2017 13:23:40 +0000
bugs1411504
milestone58.0a1
Bug 1411504. P1 - always require MediaCache to have a thread to run Update() loops. MozReview-Commit-ID: AYVWuN9CU55
dom/media/ChannelMediaResource.cpp
dom/media/MediaCache.cpp
--- a/dom/media/ChannelMediaResource.cpp
+++ b/dom/media/ChannelMediaResource.cpp
@@ -298,17 +298,17 @@ ChannelMediaResource::OnStartRequest(nsI
   mSuspendAgent.UpdateSuspendedStatusIfNeeded();
 
   // Fires an initial progress event.
   owner->DownloadProgressed();
 
   // TODO: Don't turn this on until we fix all data races.
   nsCOMPtr<nsIThreadRetargetableRequest> retarget;
   if (Preferences::GetBool("media.omt_data_delivery.enabled", false) &&
-      (retarget = do_QueryInterface(aRequest)) && mCacheStream.OwnerThread()) {
+      (retarget = do_QueryInterface(aRequest))) {
     // Note this will not always succeed. We need to handle the case where
     // all resources sharing the same cache might run their data callbacks
     // on different threads.
     retarget->RetargetDeliveryTo(mCacheStream.OwnerThread());
   }
 
   return NS_OK;
 }
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -285,28 +285,16 @@ protected:
     , mUpdateQueued(false)
 #ifdef DEBUG
     , mInUpdate(false)
 #endif
   {
     NS_ASSERTION(NS_IsMainThread(), "Only construct MediaCache on main thread");
     MOZ_COUNT_CTOR(MediaCache);
     MediaCacheFlusher::RegisterMediaCache(this);
-
-    if (!sThreadInit) {
-      sThreadInit = true;
-      nsCOMPtr<nsIThread> thread;
-      nsresult rv = NS_NewNamedThread("MediaCache", getter_AddRefs(thread));
-      if (NS_FAILED(rv)) {
-        NS_WARNING("Failed to create a thread for MediaCache.");
-        return;
-      }
-      sThread = thread.forget();
-      ClearOnShutdown(this, ShutdownPhase::ShutdownThreads);
-    }
   }
 
   ~MediaCache()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only destroy MediaCache on main thread");
     if (this == gMediaCache) {
       LOG("~MediaCache(Global file-backed MediaCache)");
       // This is the file-backed MediaCache, reset the global pointer.
@@ -457,18 +445,17 @@ protected:
   // True if an event to run Update() has been queued but not processed
   bool            mUpdateQueued;
 #ifdef DEBUG
   bool            mInUpdate;
 #endif
   // A list of resource IDs to notify about the change in suspended status.
   nsTArray<int64_t> mSuspendedStatusToNotify;
   // The thread on which we will run data callbacks from the channels.
-  // Could be null if failing to create the thread. Note this thread is shared
-  // among all MediaCache instances.
+  // Note this thread is shared among all MediaCache instances.
   static StaticRefPtr<nsIThread> sThread;
   // True if we've tried to init sThread. Note we try once only so it is safe
   // to access sThread on all threads.
   static bool sThreadInit;
 };
 
 // Initialized to nullptr by non-local static initialization.
 /* static */ MediaCache* MediaCache::gMediaCache;
@@ -724,16 +711,36 @@ MediaCache::CloseStreamsForPrivateBrowsi
     }
   }
 }
 
 /* static */ RefPtr<MediaCache>
 MediaCache::GetMediaCache(int64_t aContentLength)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
+
+  if (!sThreadInit) {
+    sThreadInit = true;
+    nsCOMPtr<nsIThread> thread;
+    nsresult rv = NS_NewNamedThread("MediaCache", getter_AddRefs(thread));
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Failed to create a thread for MediaCache.");
+      return nullptr;
+    }
+    sThread = thread.forget();
+    // Note it is safe to pass an invalid pointer for operator=(std::nullptr_t)
+    // is non-virtual and it will not access |this|.
+    ClearOnShutdown(reinterpret_cast<MediaCache*>(0x1),
+                    ShutdownPhase::ShutdownThreads);
+  }
+
+  if (!sThread) {
+    return nullptr;
+  }
+
   if (aContentLength > 0 &&
       aContentLength <= int64_t(MediaPrefs::MediaMemoryCacheMaxSize()) * 1024) {
     // Small-enough resource, use a new memory-backed MediaCache.
     RefPtr<MediaBlockCacheBase> bc = new MemoryBlockCache(aContentLength);
     nsresult rv = bc->Init();
     if (NS_SUCCEEDED(rv)) {
       RefPtr<MediaCache> mc = new MediaCache(bc);
       LOG("GetMediaCache(%" PRIi64 ") -> Memory MediaCache %p",