b=923301 add MediaStreamGraph::RunAfterPendingUpdates() r=roc
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 25 Oct 2013 12:07:29 +1300
changeset 165837 aee15d62fc009d5045828b0f15829d161bf2a3c9
parent 165836 f94365dffb6fe73e6b4f5bee500f4537688baba6
child 165838 fe16e582db9f24c80954ad596cf8e75146012c0b
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs923301
milestone27.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
b=923301 add MediaStreamGraph::RunAfterPendingUpdates() r=roc
content/media/MediaStreamGraph.cpp
content/media/MediaStreamGraph.h
content/media/MediaStreamGraphImpl.h
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -1915,16 +1915,50 @@ MediaStream::RemoveListener(MediaStreamL
   // If the stream is destroyed the Listeners have or will be
   // removed.
   if (!IsDestroyed()) {
     GraphImpl()->AppendMessage(new Message(this, aListener));
   }
 }
 
 void
+MediaStream::RunAfterPendingUpdates(nsRefPtr<nsIRunnable> aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MediaStreamGraphImpl* graph = GraphImpl();
+
+  // Special case when a non-realtime graph has not started, to ensure the
+  // runnable will run in finite time.
+  if (!(graph->mRealtime || graph->mNonRealtimeProcessing)) {
+    aRunnable->Run();
+  }
+
+  class Message : public ControlMessage {
+  public:
+    explicit Message(MediaStream* aStream,
+                     already_AddRefed<nsIRunnable> aRunnable)
+      : ControlMessage(aStream)
+      , mRunnable(aRunnable) {}
+    virtual void Run() MOZ_OVERRIDE
+    {
+      mStream->Graph()->
+        DispatchToMainThreadAfterStreamStateUpdate(mRunnable.forget());
+    }
+    virtual void RunDuringShutdown() MOZ_OVERRIDE
+    {
+      mRunnable->Run();
+    }
+  private:
+    nsRefPtr<nsIRunnable> mRunnable;
+  };
+
+  graph->AppendMessage(new Message(this, aRunnable.forget()));
+}
+
+void
 MediaStream::SetTrackEnabledImpl(TrackID aTrackID, bool aEnabled)
 {
   if (aEnabled) {
     mDisabledTrackIDs.RemoveElement(aTrackID);
   } else {
     if (!mDisabledTrackIDs.Contains(aTrackID)) {
       mDisabledTrackIDs.AppendElement(aTrackID);
     }
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -341,16 +341,30 @@ public:
   }
   // It's safe to call this even if aListener is not currently a listener;
   // the call will be ignored.
   void RemoveMainThreadListener(MainThreadMediaStreamListener* aListener)
   {
     NS_ASSERTION(NS_IsMainThread(), "Call only on main thread");
     mMainThreadListeners.RemoveElement(aListener);
   }
+  /**
+   * Ensure a runnable will run on the main thread after running all pending
+   * updates that were sent from the graph thread or will be sent before the
+   * graph thread receives the next graph update.
+   *
+   * If the graph has been shutdown or destroyed, or if it is non-realtime
+   * and has not started, then the runnable will be run
+   * synchronously/immediately.  (There are no pending updates in these
+   * situations.)
+   *
+   * Main thread only.
+   */
+  void RunAfterPendingUpdates(nsRefPtr<nsIRunnable> aRunnable);
+
   // Signal that the client is done with this MediaStream. It will be deleted later.
   virtual void Destroy();
   // Returns the main-thread's view of how much data has been processed by
   // this stream.
   StreamTime GetCurrentTime()
   {
     NS_ASSERTION(NS_IsMainThread(), "Call only on main thread");
     return mMainThreadCurrentTime;
--- a/content/media/MediaStreamGraphImpl.h
+++ b/content/media/MediaStreamGraphImpl.h
@@ -67,21 +67,21 @@ struct StreamUpdate {
   int64_t mGraphUpdateIndex;
   nsRefPtr<MediaStream> mStream;
   StreamTime mNextMainThreadCurrentTime;
   bool mNextMainThreadFinished;
 };
 
 /**
  * This represents a message passed from the main thread to the graph thread.
- * A ControlMessage always references a particular affected stream.
+ * A ControlMessage always has a weak reference a particular affected stream.
  */
 class ControlMessage {
 public:
-  ControlMessage(MediaStream* aStream) : mStream(aStream)
+  explicit ControlMessage(MediaStream* aStream) : mStream(aStream)
   {
     MOZ_COUNT_CTOR(ControlMessage);
   }
   // All these run on the graph thread
   virtual ~ControlMessage()
   {
     MOZ_COUNT_DTOR(ControlMessage);
   }