Bug 1341555 - Label MSG runnables. r=pehrsons
authorPaul Adenot <paul@paul.cx>
Thu, 29 Jun 2017 11:31:17 -0700
changeset 366745 e0c4f2ca44b4292881a56fab6bf584bf7d966299
parent 366744 5de53323f3ad17102b9428fc3c06066055cabc73
child 366746 5c2fea87df168bdcbfe807ffedfb6d7c1ea4cb4e
push id92039
push userpaul@paul.cx
push dateThu, 29 Jun 2017 20:39:37 +0000
treeherdermozilla-inbound@29ac12c81bcd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspehrsons
bugs1341555
milestone56.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 1341555 - Label MSG runnables. r=pehrsons MozReview-Commit-ID: 4sfRH3FxtBT
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/MediaStreamGraphImpl.h
dom/media/webaudio/AudioDestinationNode.cpp
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1007,19 +1007,20 @@ MediaStreamGraphImpl::OpenAudioInputImpl
 }
 
 nsresult
 MediaStreamGraphImpl::OpenAudioInput(int aID,
                                      AudioDataListener *aListener)
 {
   // So, so, so annoying.  Can't AppendMessage except on Mainthread
   if (!NS_IsMainThread()) {
-    NS_DispatchToMainThread(WrapRunnable(this,
-                                         &MediaStreamGraphImpl::OpenAudioInput,
-                                         aID, RefPtr<AudioDataListener>(aListener)));
+    RefPtr<nsIRunnable> runnable = WrapRunnable(this,
+                                  &MediaStreamGraphImpl::OpenAudioInput,
+                                  aID, RefPtr<AudioDataListener>(aListener));
+    mAbstractMainThread->Dispatch(runnable.forget());
     return NS_OK;
   }
   class Message : public ControlMessage {
   public:
     Message(MediaStreamGraphImpl *aGraph, int aID,
             AudioDataListener *aListener) :
       ControlMessage(nullptr), mGraph(aGraph), mID(aID), mListener(aListener) {}
     virtual void Run()
@@ -1077,19 +1078,20 @@ MediaStreamGraphImpl::CloseAudioInputImp
   }
 }
 
 void
 MediaStreamGraphImpl::CloseAudioInput(AudioDataListener *aListener)
 {
   // So, so, so annoying.  Can't AppendMessage except on Mainthread
   if (!NS_IsMainThread()) {
-    NS_DispatchToMainThread(WrapRunnable(this,
-                                         &MediaStreamGraphImpl::CloseAudioInput,
-                                         RefPtr<AudioDataListener>(aListener)));
+    RefPtr<nsIRunnable> runnable = WrapRunnable(this,
+                                                &MediaStreamGraphImpl::CloseAudioInput,
+                                                RefPtr<AudioDataListener>(aListener));
+    mAbstractMainThread->Dispatch(runnable.forget());
     return;
   }
   class Message : public ControlMessage {
   public:
     Message(MediaStreamGraphImpl *aGraph, AudioDataListener *aListener) :
       ControlMessage(nullptr), mGraph(aGraph), mListener(aListener) {}
     virtual void Run()
     {
@@ -1698,17 +1700,17 @@ MediaStreamGraphImpl::RunInStableState(b
         // A new graph graph will be created if one is needed.
         // Asynchronously clean up old graph. We don't want to do this
         // synchronously because it spins the event loop waiting for threads
         // to shut down, and we don't want to do that in a stable state handler.
         mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
         LOG(LogLevel::Debug,
             ("Sending MediaStreamGraphShutDownRunnable %p", this));
         nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this );
-        NS_DispatchToMainThread(event.forget());
+        mAbstractMainThread->Dispatch(event.forget());
 
         LOG(LogLevel::Debug, ("Disconnecting MediaStreamGraph %p", this));
 
         // Find the graph in the hash table and remove it.
         for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
           if (iter.UserData() == this) {
             iter.Remove();
             break;
@@ -1781,17 +1783,17 @@ MediaStreamGraphImpl::RunInStableState(b
         controlMessagesToRunDuringShutdown.AppendElements(Move(mb.mMessages));
       }
       mBackMessageQueue.Clear();
       MOZ_ASSERT(mCurrentTaskMessageQueue.IsEmpty());
       // Stop MediaStreamGraph threads. Do not clear gGraph since
       // we have outstanding DOM objects that may need it.
       mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
       nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this);
-      NS_DispatchToMainThread(event.forget());
+      mAbstractMainThread->Dispatch(event.forget());
     }
 
     mDetectedNotRunning = mLifecycleState > LIFECYCLE_RUNNING;
   }
 
   // Make sure we get a new current time in the next event loop task
   if (!aSourceIsMSG) {
     MOZ_ASSERT(mPostedRunInStableState);
@@ -1829,17 +1831,17 @@ void
 MediaStreamGraphImpl::EnsureStableStateEventPosted()
 {
   mMonitor.AssertCurrentThreadOwns();
 
   if (mPostedRunInStableStateEvent)
     return;
   mPostedRunInStableStateEvent = true;
   nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable(this, true);
-  NS_DispatchToMainThread(event.forget());
+  mAbstractMainThread->Dispatch(event.forget());
 }
 
 void
 MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread(), "main thread only");
   MOZ_ASSERT(!aMessage->GetStream() ||
              !aMessage->GetStream()->IsDestroyed(),
@@ -1876,16 +1878,22 @@ MediaStreamGraphImpl::AppendMessage(Uniq
     }
     return;
   }
 
   mCurrentTaskMessageQueue.AppendElement(Move(aMessage));
   EnsureRunInStableState();
 }
 
+void
+MediaStreamGraphImpl::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable)
+{
+  mAbstractMainThread->Dispatch(Move(aRunnable));
+}
+
 MediaStream::MediaStream(AbstractThread* aMainThread)
   : mTracksStartTime(0)
   , mStartBlocking(GRAPH_TIME_MAX)
   , mSuspendedCount(0)
   , mFinished(false)
   , mNotifiedFinished(false)
   , mNotifiedBlocked(false)
   , mHasCurrentData(false)
@@ -2558,17 +2566,17 @@ MediaStream::RunAfterPendingUpdates(alre
         DispatchToMainThreadAfterStreamStateUpdate(mAbstractMainThread,
                                                    mRunnable.forget());
     }
     void RunDuringShutdown() override
     {
       // Don't run mRunnable now as it may call AppendMessage() which would
       // assume that there are no remaining controlMessagesToRunDuringShutdown.
       MOZ_ASSERT(NS_IsMainThread());
-      NS_DispatchToCurrentThread(mRunnable);
+      mStream->GraphImpl()->Dispatch(mRunnable.forget());
     }
   private:
     nsCOMPtr<nsIRunnable> mRunnable;
     const RefPtr<AbstractThread> mAbstractMainThread;
   };
 
   graph->AppendMessage(
     MakeUnique<Message>(this, runnable.forget(), mAbstractMainThread));
@@ -2678,17 +2686,17 @@ MediaStream::AddMainThreadListener(MainT
 
   private:
     ~NotifyRunnable() {}
 
     RefPtr<MediaStream> mStream;
   };
 
   nsCOMPtr<nsIRunnable> runnable = new NotifyRunnable(this);
-  Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable.forget())));
+  mAbstractMainThread->Dispatch(runnable.forget());
 }
 
 SourceMediaStream::SourceMediaStream(AbstractThread* aMainThread) :
   MediaStream(aMainThread),
   mMutex("mozilla::media::SourceMediaStream"),
   mUpdateKnownTracksTime(0),
   mPullEnabled(false),
   mUpdateFinished(false),
@@ -3415,17 +3423,18 @@ ProcessedMediaStream::DestroyImpl()
   // The stream order is only important if there are connections, in which
   // case MediaInputPort::Disconnect() called SetStreamOrderDirty().
   // MediaStreamGraphImpl::RemoveStreamGraphThread() will also call
   // SetStreamOrderDirty(), for other reasons.
 }
 
 MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
                                            TrackRate aSampleRate,
-                                           dom::AudioChannel aChannel)
+                                           dom::AudioChannel aChannel,
+                                           AbstractThread* aMainThread)
   : MediaStreamGraph(aSampleRate)
   , mPortCount(0)
   , mInputWanted(false)
   , mInputDeviceID(-1)
   , mOutputWanted(true)
   , mOutputDeviceID(-1)
   , mNeedAnotherIteration(false)
   , mGraphDriverAsleep(false)
@@ -3443,16 +3452,17 @@ MediaStreamGraphImpl::MediaStreamGraphIm
 #ifdef MOZ_WEBRTC
   , mFarendObserverRef(nullptr)
 #endif
   , mSelfRef(this)
 #ifdef DEBUG
   , mCanRunMessagesSynchronously(false)
 #endif
   , mAudioChannel(aChannel)
+  , mAbstractMainThread(aMainThread)
 {
   if (mRealtime) {
     if (aDriverRequested == AUDIO_THREAD_DRIVER) {
       AudioCallbackDriver* driver = new AudioCallbackDriver(this);
       mDriver = driver;
     } else {
       mDriver = new SystemClockDriver(this);
     }
@@ -3535,39 +3545,51 @@ MediaStreamGraph::GetInstance(MediaStrea
       nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
       nsresult rv = barrier->
           AddBlocker(gMediaStreamGraphShutdownBlocker,
                      NS_LITERAL_STRING(__FILE__), __LINE__,
                      NS_LITERAL_STRING("MediaStreamGraph shutdown"));
       MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
     }
 
+    AbstractThread* mainThread;
+    if (aWindow) {
+      nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(aWindow);
+      mainThread = parentObject->AbstractMainThreadFor(TaskCategory::Other);
+    } else {
+      // Uncommon case, only for some old configuration of webspeech.
+      mainThread = AbstractThread::MainThread();
+    }
     graph = new MediaStreamGraphImpl(aGraphDriverRequested,
                                      CubebUtils::PreferredSampleRate(),
-                                     aChannel);
+                                     aChannel,
+                                     mainThread);
 
     gGraphs.Put(hashkey, graph);
 
     LOG(LogLevel::Debug,
         ("Starting up MediaStreamGraph %p for channel %s and window %p",
          graph, AudioChannelValues::strings[channel].value, aWindow));
   }
 
   return graph;
 }
 
 MediaStreamGraph*
-MediaStreamGraph::CreateNonRealtimeInstance(TrackRate aSampleRate)
+MediaStreamGraph::CreateNonRealtimeInstance(TrackRate aSampleRate,
+                                            nsPIDOMWindowInner* aWindow)
 {
   NS_ASSERTION(NS_IsMainThread(), "Main thread only");
 
+  nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(aWindow);
   MediaStreamGraphImpl* graph =
     new MediaStreamGraphImpl(OFFLINE_THREAD_DRIVER,
                              aSampleRate,
-                             AudioChannel::Normal);
+                             AudioChannel::Normal,
+                             parentObject->AbstractMainThreadFor(TaskCategory::Other));
 
   LOG(LogLevel::Debug, ("Starting up Offline MediaStreamGraph %p", graph));
 
   return graph;
 }
 
 void
 MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
@@ -3677,17 +3699,17 @@ MediaStreamGraphImpl::CollectSizesForMem
   for (MediaStream* s : AllStreams()) {
     AudioNodeStream* stream = s->AsAudioNodeStream();
     if (stream) {
       AudioNodeSizes* usage = audioStreamSizes->AppendElement();
       stream->SizeOfAudioNodesIncludingThis(MallocSizeOf, *usage);
     }
   }
 
-  NS_DispatchToMainThread(runnable.forget());
+  mAbstractMainThread->Dispatch(runnable.forget());
 }
 
 void
 MediaStreamGraphImpl::
 FinishCollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
                      const nsTArray<AudioNodeSizes>& aAudioStreamSizes)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -3801,21 +3823,21 @@ MediaStreamGraph::NotifyWhenGraphStarted
       // This runs on the graph thread, so when this runs, and the current
       // driver is an AudioCallbackDriver, we know the audio hardware is
       // started. If not, we are going to switch soon, keep reposting this
       // ControlMessage.
       MediaStreamGraphImpl* graphImpl = mStream->GraphImpl();
       if (graphImpl->CurrentDriver()->AsAudioCallbackDriver()) {
         nsCOMPtr<nsIRunnable> event = new dom::StateChangeTask(
             mStream->AsAudioNodeStream(), nullptr, AudioContextState::Running);
-        NS_DispatchToMainThread(event.forget());
+        graphImpl->Dispatch(event.forget());
       } else {
         nsCOMPtr<nsIRunnable> event = new GraphStartedRunnable(
             mStream->AsAudioNodeStream(), mStream->Graph());
-        NS_DispatchToMainThread(event.forget());
+        graphImpl->Dispatch(event.forget());
       }
     }
     void RunDuringShutdown() override
     {
     }
   };
 
   if (!aStream->IsDestroyed()) {
@@ -3904,17 +3926,17 @@ MediaStreamGraphImpl::AudioContextOperat
     case AudioContextOperation::Close:
       state = AudioContextState::Closed;
       break;
     default: MOZ_CRASH("Not handled.");
   }
 
   nsCOMPtr<nsIRunnable> event = new dom::StateChangeTask(
       aStream->AsAudioNodeStream(), aPromise, state);
-  NS_DispatchToMainThread(event.forget());
+  mAbstractMainThread->Dispatch(event.forget());
 }
 
 void
 MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
     MediaStream* aDestinationStream, const nsTArray<MediaStream*>& aStreams,
     AudioContextOperation aOperation, void* aPromise)
 {
   MOZ_ASSERT(CurrentDriver()->OnThread());
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -17,16 +17,17 @@
 #include "mozilla/dom/AudioChannelBinding.h"
 #include "nsAutoPtr.h"
 #include "nsAutoRef.h"
 #include "nsIRunnable.h"
 #include "nsTArray.h"
 #include <speex/speex_resampler.h>
 
 class nsIRunnable;
+class nsIGlobalObject;
 class nsPIDOMWindowInner;
 
 template <>
 class nsAutoRefTraits<SpeexResamplerState> : public nsPointerRefTraits<SpeexResamplerState>
 {
   public:
   static void Release(SpeexResamplerState* aState) { speex_resampler_destroy(aState); }
 };
@@ -1271,17 +1272,18 @@ public:
     OFFLINE_THREAD_DRIVER
   };
   static const uint32_t AUDIO_CALLBACK_DRIVER_SHUTDOWN_TIMEOUT = 20*1000;
 
   // Main thread only
   static MediaStreamGraph* GetInstance(GraphDriverType aGraphDriverRequested,
                                        dom::AudioChannel aChannel,
                                        nsPIDOMWindowInner* aWindow);
-  static MediaStreamGraph* CreateNonRealtimeInstance(TrackRate aSampleRate);
+  static MediaStreamGraph* CreateNonRealtimeInstance(TrackRate aSampleRate,
+                                                     nsPIDOMWindowInner* aWindowId);
   // Idempotent
   static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph);
 
   virtual nsresult OpenAudioInput(int aID,
                                   AudioDataListener *aListener) {
     return NS_ERROR_FAILURE;
   }
   virtual void CloseAudioInput(AudioDataListener *aListener) {}
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -111,17 +111,18 @@ public:
    * to create a MediaStreamGraph which provides support for real-time audio
    * and/or video.  Set it to OFFLINE_THREAD_DRIVER in order to create a
    * non-realtime instance which just churns through its inputs and produces
    * output.  Those objects currently only support audio, and are used to
    * implement OfflineAudioContext.  They do not support MediaStream inputs.
    */
   explicit MediaStreamGraphImpl(GraphDriverType aGraphDriverRequested,
                                 TrackRate aSampleRate,
-                                dom::AudioChannel aChannel);
+                                dom::AudioChannel aChannel,
+                                AbstractThread* aWindow);
 
   /**
    * Unregisters memory reporting and deletes this instance. This should be
    * called instead of calling the destructor directly.
    */
   void Destroy();
 
   // Main thread only.
@@ -144,16 +145,22 @@ public:
    */
   void ApplyStreamUpdate(StreamUpdate* aUpdate);
   /**
    * Append a ControlMessage to the message queue. This queue is drained
    * during RunInStableState; the messages will run on the graph thread.
    */
   void AppendMessage(UniquePtr<ControlMessage> aMessage);
 
+  /**
+   * Dispatches a runnable from any thread to the correct main thread for this
+   * MediaStreamGraph.
+   */
+  void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable);
+
   // Shutdown helpers.
 
   static already_AddRefed<nsIAsyncShutdownClient>
   GetShutdownBarrier()
   {
     nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
     MOZ_RELEASE_ASSERT(svc);
 
@@ -841,13 +848,14 @@ private:
 #ifdef DEBUG
   /**
    * Used to assert when AppendMessage() runs ControlMessages synchronously.
    */
   bool mCanRunMessagesSynchronously;
 #endif
 
   dom::AudioChannel mAudioChannel;
+  const RefPtr<AbstractThread> mAbstractMainThread;
 };
 
 } // namespace mozilla
 
 #endif /* MEDIASTREAMGRAPHIMPL_H_ */
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -332,17 +332,17 @@ AudioDestinationNode::AudioDestinationNo
   , mAudioChannel(AudioChannel::Normal)
   , mIsOffline(aIsOffline)
   , mAudioChannelSuspended(false)
   , mCaptured(false)
   , mAudible(AudioChannelService::AudibleState::eAudible)
 {
   nsPIDOMWindowInner* window = aContext->GetParentObject();
   MediaStreamGraph* graph = aIsOffline ?
-                            MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate) :
+                            MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate, window) :
                             MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER, aChannel, window);
   AudioNodeEngine* engine = aIsOffline ?
                             new OfflineDestinationNodeEngine(this, aNumberOfChannels,
                                                              aLength, aSampleRate) :
                             static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this));
 
   AudioNodeStream::Flags flags =
     AudioNodeStream::NEED_MAIN_THREAD_CURRENT_TIME |