Bug 1161901 - Make MDSM::ScheduleStateMachine runs on the state machine task queue only. r=jww
authorBobby Holley <bobbyholley@gmail.com>
Tue, 05 May 2015 18:17:51 -0700
changeset 274209 6777dea98c1fd7231584b22a17b9758cfefb9691
parent 274208 6f05b1eb33ab1ddec478b4756372bd5cc96f2313
child 274210 fa9d94918e1211f9350272a995003eb58b23ad29
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjww
bugs1161901
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1161901 - Make MDSM::ScheduleStateMachine runs on the state machine task queue only. r=jww
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/mediasource/MediaSourceDecoder.cpp
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -565,17 +565,17 @@ void MediaDecoder::AddOutputStream(Proce
   }
 
   // This can be called before Load(), in which case our mDecoderStateMachine
   // won't have been created yet and we can rely on Load() to schedule it
   // once it is created.
   if (mDecoderStateMachine) {
     // Make sure the state machine thread runs so that any buffered data
     // is fed into our stream.
-    ScheduleStateMachineThread();
+    ScheduleStateMachine();
   }
 }
 
 double MediaDecoder::GetDuration()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mInfiniteStream) {
     return std::numeric_limits<double>::infinity();
@@ -750,17 +750,17 @@ nsresult MediaDecoder::InitializeStateMa
   nsresult rv = mDecoderStateMachine->Init(
       cloneDonor ? cloneDonor->mDecoderStateMachine : nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If some parameters got set before the state machine got created,
   // set them now
   SetStateMachineParameters();
 
-  return ScheduleStateMachineThread();
+  return ScheduleStateMachine();
 }
 
 void MediaDecoder::SetStateMachineParameters()
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mDecoderStateMachine->SetDuration(mDuration);
   if (GetDecodedStream()) {
     mDecoderStateMachine->DispatchAudioCaptured();
@@ -776,41 +776,41 @@ void MediaDecoder::SetMinimizePrerollUnt
   MOZ_ASSERT(NS_IsMainThread());
   mMinimizePreroll = true;
 
   // This needs to be called before we init the state machine, otherwise it will
   // have no effect.
   MOZ_DIAGNOSTIC_ASSERT(!mDecoderStateMachine);
 }
 
-nsresult MediaDecoder::ScheduleStateMachineThread()
+nsresult MediaDecoder::ScheduleStateMachine()
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ASSERTION(mDecoderStateMachine,
                "Must have state machine to start state machine thread");
   NS_ENSURE_STATE(mDecoderStateMachine);
 
   if (mShuttingDown)
     return NS_OK;
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
-  mDecoderStateMachine->ScheduleStateMachine();
+  mDecoderStateMachine->ScheduleStateMachineCrossThread();
   return NS_OK;
 }
 
 nsresult MediaDecoder::Play()
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
 
   NS_ASSERTION(mDecoderStateMachine != nullptr, "Should have state machine.");
   if (mPausedForPlaybackRateNull) {
     return NS_OK;
   }
-  ScheduleStateMachineThread();
+  ScheduleStateMachine();
   if (IsEnded()) {
     return Seek(0, SeekTarget::PrevSyncPoint);
   } else if (mPlayState == PLAY_STATE_LOADING) {
     mNextState = PLAY_STATE_PLAYING;
     return NS_OK;
   }
 
   ChangeState(PLAY_STATE_PLAYING);
@@ -1305,17 +1305,17 @@ void MediaDecoder::ChangeState(PlayState
   UpdateDecodedStream();
 
   if (mPlayState == PLAY_STATE_PLAYING) {
     ConstructMediaTracks();
   } else if (IsEnded()) {
     RemoveMediaTracks();
   }
 
-  ScheduleStateMachineThread();
+  ScheduleStateMachine();
 
   CancelDormantTimer();
   // Start dormant timer if necessary
   StartDormantTimer();
 
   GetReentrantMonitor().NotifyAll();
 }
 
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -884,17 +884,17 @@ public:
 #endif
 
 #ifdef MOZ_APPLEMEDIA
   static bool IsAppleMP3Enabled();
 #endif
 
   // Schedules the state machine to run one cycle on the shared state
   // machine thread. Main thread only.
-  nsresult ScheduleStateMachineThread();
+  nsresult ScheduleStateMachine();
 
   struct Statistics {
     // Estimate of the current playback rate (bytes/second).
     double mPlaybackRate;
     // Estimate of the current download rate (bytes/second). This
     // ignores time that the channel was paused by Gecko.
     double mDownloadRate;
     // Total length of media stream in bytes; -1 if not known
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -3301,16 +3301,17 @@ void MediaDecoderStateMachine::ScheduleS
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   DispatchAudioDecodeTaskIfNeeded();
   DispatchVideoDecodeTaskIfNeeded();
 }
 
 void
 MediaDecoderStateMachine::ScheduleStateMachine() {
+  MOZ_ASSERT(OnTaskQueue());
   AssertCurrentThreadInMonitor();
   if (mDispatchedStateMachine) {
     return;
   }
   mDispatchedStateMachine = true;
 
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableMethod(this, &MediaDecoderStateMachine::RunStateMachine);
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -321,17 +321,27 @@ public:
   // Returns the state machine task queue.
   MediaTaskQueue* TaskQueue() const { return mTaskQueue; }
 
   // Calls ScheduleStateMachine() after taking the decoder lock. Also
   // notifies the decoder thread in case it's waiting on the decoder lock.
   void ScheduleStateMachineWithLockAndWakeDecoder();
 
   // Schedules the shared state machine thread to run the state machine.
+  //
+  // The first variant coalesces multiple calls into a single state machine
+  // cycle, the second variant does not. The second variant must be used when
+  // not already on the state machine task queue.
   void ScheduleStateMachine();
+  void ScheduleStateMachineCrossThread()
+  {
+    nsCOMPtr<nsIRunnable> task =
+      NS_NewRunnableMethod(this, &MediaDecoderStateMachine::RunStateMachine);
+    TaskQueue()->Dispatch(task.forget());
+  }
 
   // Invokes ScheduleStateMachine to run in |aMicroseconds| microseconds,
   // unless it's already scheduled to run earlier, in which case the
   // request is discarded.
   void ScheduleStateMachineIn(int64_t aMicroseconds);
 
   void OnDelayedSchedule()
   {
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -60,17 +60,17 @@ MediaSourceDecoder::Load(nsIStreamListen
     NS_WARNING("Failed to create state machine!");
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = GetStateMachine()->Init(nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SetStateMachineParameters();
-  return ScheduleStateMachineThread();
+  return ScheduleStateMachine();
 }
 
 nsresult
 MediaSourceDecoder::GetSeekable(dom::TimeRanges* aSeekable)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mMediaSource) {
     return NS_ERROR_FAILURE;