Bug 1072780 - Patch 3: Fix up Revive() to not trigger assertions, and also to avoid Init() (blocking) on MainThread. r=roc, a=lmandel
authorRandell Jesup <rjesup@jesup.org>
Sun, 28 Sep 2014 12:07:24 -0400
changeset 225442 e3397237012d16c364a5a403df91273299dce19f
parent 225441 6fc7dace7ec946e2e5c2a727a55feb7a70421a39
child 225443 5ef997137570b8a5470565189f4c7789bdb732cf
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, lmandel
bugs1072780
milestone34.0a2
Bug 1072780 - Patch 3: Fix up Revive() to not trigger assertions, and also to avoid Init() (blocking) on MainThread. r=roc, a=lmandel
content/media/GraphDriver.cpp
content/media/MediaStreamGraphImpl.h
--- a/content/media/GraphDriver.cpp
+++ b/content/media/GraphDriver.cpp
@@ -220,31 +220,38 @@ private:
   ThreadedDriver* mDriver;
 };
 
 void
 ThreadedDriver::Start()
 {
   LIFECYCLE_LOG("Starting thread for a SystemClockDriver  %p\n", mGraphImpl);
   nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
-  NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
+  // Note: mThread may be null during event->Run() if we pass to NewNamedThread!  See AudioInitTask
+  nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread));
+  if (NS_SUCCEEDED(rv)) {
+    mThread->Dispatch(event, NS_DISPATCH_NORMAL);
+  }
 }
 
 void
 ThreadedDriver::Resume()
 {
   Start();
 }
 
 void
 ThreadedDriver::Revive()
 {
+  // Note: only called on MainThread, without monitor
+  // We know were weren't in a running state
   STREAM_LOG(PR_LOG_DEBUG, ("AudioCallbackDriver reviving."));
   // If we were switching, switch now. Otherwise, tell thread to run the main
   // loop again.
+  MonitorAutoLock mon(mGraphImpl->GetMonitor());
   if (mNextDriver) {
     mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd,
                                mStateComputedTime, mNextStateComputedTime);
     mGraphImpl->SetCurrentDriver(mNextDriver);
     mNextDriver->Start();
   } else {
     nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
     mThread->Dispatch(event, NS_DISPATCH_NORMAL);
@@ -661,26 +668,31 @@ AudioCallbackDriver::Stop()
   if (cubeb_stream_stop(mAudioStream) != CUBEB_OK) {
     NS_WARNING("Could not stop cubeb stream for MSG.");
   }
 }
 
 void
 AudioCallbackDriver::Revive()
 {
+  // Note: only called on MainThread, without monitor
+  // We know were weren't in a running state
   STREAM_LOG(PR_LOG_DEBUG, ("AudioCallbackDriver reviving."));
   // If we were switching, switch now. Otherwise, start the audio thread again.
+  MonitorAutoLock mon(mGraphImpl->GetMonitor());
   if (mNextDriver) {
     mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd,
-                               mStateComputedTime, mNextStateComputedTime);
+                              mStateComputedTime, mNextStateComputedTime);
     mGraphImpl->SetCurrentDriver(mNextDriver);
     mNextDriver->Start();
   } else {
-    Init();
-    Start();
+    STREAM_LOG(PR_LOG_DEBUG, ("Starting audio threads for MediaStreamGraph %p from a new thread.", mGraphImpl));
+    nsRefPtr<AsyncCubebTask> initEvent =
+      new AsyncCubebTask(this, AsyncCubebTask::INIT);
+    initEvent->Dispatch();
   }
 }
 
 void
 AudioCallbackDriver::GetIntervalForIteration(GraphTime& aFrom,
                                              GraphTime& aTo)
 {
 }
--- a/content/media/MediaStreamGraphImpl.h
+++ b/content/media/MediaStreamGraphImpl.h
@@ -433,19 +433,26 @@ public:
     return mDriver;
   }
 
   /**
    * Effectively set the new driver, while we are switching.
    * It is only safe to call this at the very end of an iteration, when there
    * has been a SwitchAtNextIteration call during the iteration. The driver
    * should return and pass the control to the new driver shortly after.
+   * We can also switch from Revive() (on MainThread), in which case the
+   * monitor is held
    */
   void SetCurrentDriver(GraphDriver* aDriver) {
-    MOZ_ASSERT(mDriver->OnThread());
+#ifdef DEBUG
+    // #ifdef since we're not wrapping it all in MOZ_ASSERT()
+    if (!mDriver->OnThread()) {
+      mMonitor.AssertCurrentThreadOwns();
+    }
+#endif
     mDriver = aDriver;
   }
 
   Monitor& GetMonitor() {
     return mMonitor;
   }
 
   /**