bug 1172377 change RunInStableState API to receive ownership of nsIRunnable r=roc
authorKarl Tomlinson <karlt+@karlt.net>
Mon, 08 Jun 2015 11:06:38 +1200
changeset 278996 208891d8e3884b19838a495906697d0363d501a8
parent 278995 b61b49cd8e9b3594240b1c2b007ba1e718096888
child 278997 a7e2543f579ed91dd4f971dbd02573e100ebab2d
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1172377
milestone41.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 1172377 change RunInStableState API to receive ownership of nsIRunnable r=roc
dom/base/nsContentUtils.cpp
widget/ScreenProxy.cpp
widget/nsBaseAppShell.cpp
widget/nsBaseAppShell.h
widget/nsIAppShell.idl
widget/nsScreenManagerProxy.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -5157,19 +5157,17 @@ nsContentUtils::RunInStableState(already
                                  DispatchFailureHandling aHandling)
 {
   nsCOMPtr<nsIRunnable> runnable = aRunnable;
   nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
   if (!appShell) {
     MOZ_ASSERT(aHandling == DispatchFailureHandling::IgnoreFailure);
     return;
   }
-  DebugOnly<nsresult> rv = appShell->RunInStableState(runnable);
-  MOZ_ASSERT(NS_SUCCEEDED(rv) ||
-             aHandling == DispatchFailureHandling::IgnoreFailure);
+  appShell->RunInStableState(runnable.forget());
 }
 
 void
 nsContentUtils::EnterMicroTask()
 {
   MOZ_ASSERT(NS_IsMainThread());
   ++sMicroTaskLevel;
 }
--- a/widget/ScreenProxy.cpp
+++ b/widget/ScreenProxy.cpp
@@ -166,19 +166,19 @@ ScreenProxy::InvalidateCacheOnNextTick()
   if (mCacheWillInvalidate) {
     return;
   }
 
   mCacheWillInvalidate = true;
 
   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
   if (appShell) {
-    appShell->RunInStableState(
-      NS_NewRunnableMethod(this, &ScreenProxy::InvalidateCache)
-    );
+    nsCOMPtr<nsIRunnable> r =
+      NS_NewRunnableMethod(this, &ScreenProxy::InvalidateCache);
+    appShell->RunInStableState(r.forget());
   } else {
     // It's pretty bad news if we can't get the appshell. In that case,
     // let's just invalidate the cache right away.
     InvalidateCache();
   }
 }
 
 void
--- a/widget/nsBaseAppShell.cpp
+++ b/widget/nsBaseAppShell.cpp
@@ -382,17 +382,18 @@ nsBaseAppShell::RunSyncSectionsInternal(
     }
   }
 
   mSyncSections.SwapElements(pendingSyncSections);
   mRunningSyncSections = false;
 }
 
 void
-nsBaseAppShell::ScheduleSyncSection(nsIRunnable* aRunnable, bool aStable)
+nsBaseAppShell::ScheduleSyncSection(already_AddRefed<nsIRunnable> aRunnable,
+                                    bool aStable)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   nsIThread* thread = NS_GetCurrentThread();
 
   // Add this runnable to our list of synchronous sections.
   SyncSection* section = mSyncSections.AppendElement();
   section->mStable = aStable;
@@ -439,21 +440,21 @@ NS_IMETHODIMP
 nsBaseAppShell::Observe(nsISupports *subject, const char *topic,
                         const char16_t *data)
 {
   NS_ASSERTION(!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID), "oops");
   Exit();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsBaseAppShell::RunInStableState(nsIRunnable* aRunnable)
+void
+nsBaseAppShell::RunInStableState(already_AddRefed<nsIRunnable> aRunnable)
 {
-  ScheduleSyncSection(aRunnable, true);
-  return NS_OK;
+  ScheduleSyncSection(mozilla::Move(aRunnable), true);
 }
 
 NS_IMETHODIMP
 nsBaseAppShell::RunBeforeNextEvent(nsIRunnable* aRunnable)
 {
-  ScheduleSyncSection(aRunnable, false);
+  nsCOMPtr<nsIRunnable> runnable = aRunnable;
+  ScheduleSyncSection(runnable.forget(), false);
   return NS_OK;
 }
--- a/widget/nsBaseAppShell.h
+++ b/widget/nsBaseAppShell.h
@@ -20,16 +20,18 @@
  * to enable platform-specific event queue support.
  */
 class nsBaseAppShell : public nsIAppShell, public nsIThreadObserver,
                        public nsIObserver
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIAPPSHELL
+  void RunInStableState(already_AddRefed<nsIRunnable> runnable) override;
+
   NS_DECL_NSITHREADOBSERVER
   NS_DECL_NSIOBSERVER
 
   nsBaseAppShell();
 
 protected:
   virtual ~nsBaseAppShell();
 
@@ -89,17 +91,17 @@ private:
 
   void RunSyncSections(bool stable, uint32_t threadRecursionLevel)
   {
     if (!mSyncSections.IsEmpty()) {
       RunSyncSectionsInternal(stable, threadRecursionLevel);
     }
   }
 
-  void ScheduleSyncSection(nsIRunnable* runnable, bool stable);
+  void ScheduleSyncSection(already_AddRefed<nsIRunnable> runnable, bool stable);
 
   struct SyncSection {
     SyncSection()
     : mStable(false), mEventloopNestingLevel(0), mThreadRecursionLevel(0)
     { }
 
     void Forget(SyncSection* other) {
       other->mStable = mStable;
--- a/widget/nsIAppShell.idl
+++ b/widget/nsIAppShell.idl
@@ -2,22 +2,25 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIRunnable;
+%{ C++
+template <class T> struct already_AddRefed;
+%}
 
 /**
  * Interface for the native event system layer.  This interface is designed
  * to be used on the main application thread only.
  */
-[uuid(2d10ca53-f143-439a-bb2e-c1fbc71f6a05)]
+[uuid(3d09973e-3975-4fd4-b103-276300cc8437)]
 interface nsIAppShell : nsISupports
 {
   /**
    * Enter an event loop.  Don't leave until exit() is called.
    */
   void run();
 
   /**
@@ -66,26 +69,30 @@ interface nsIAppShell : nsISupports
    */
   void resumeNative();
 
   /**
    * The current event loop nesting level.
    */
   readonly attribute unsigned long eventloopNestingLevel;
   
+%{ C++
   /**
-   * Allows running of a "synchronous section", in the form of an nsIRunnable
-   * once the event loop has reached a "stable state". We've reached a stable
-   * state when the currently executing task/event has finished, see:
+   * Add a "synchronous section", in the form of an nsIRunnable run once the
+   * event loop has reached a "stable state". |runnable| must not cause any
+   * queued events to be processed (i.e. must not spin the event loop). We've
+   * reached a stable state when the currently executing task/event has
+   * finished, see:
    * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
    * In practice this runs aRunnable once the currently executing event
    * finishes. If called multiple times per task/event, all the runnables will
    * be executed, in the order in which runInStableState() was called.
    */
-  void runInStableState(in nsIRunnable runnable);
+  virtual void RunInStableState(already_AddRefed<nsIRunnable> runnable) = 0;
+%}
 
   /**
    * Run the given runnable before the next iteration of the event loop (this
    * includes native events too). If a nested loop is spawned within the current
    * event then the runnable will not be run until that loop has terminated.
    */
   void runBeforeNextEvent(in nsIRunnable runnable);
 };
--- a/widget/nsScreenManagerProxy.cpp
+++ b/widget/nsScreenManagerProxy.cpp
@@ -195,19 +195,19 @@ nsScreenManagerProxy::InvalidateCacheOnN
   if (mCacheWillInvalidate) {
     return;
   }
 
   mCacheWillInvalidate = true;
 
   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
   if (appShell) {
-    appShell->RunInStableState(
-      NS_NewRunnableMethod(this, &nsScreenManagerProxy::InvalidateCache)
-    );
+    nsCOMPtr<nsIRunnable> r =
+      NS_NewRunnableMethod(this, &nsScreenManagerProxy::InvalidateCache);
+    appShell->RunInStableState(r.forget());
   } else {
     // It's pretty bad news if we can't get the appshell. In that case,
     // let's just invalidate the cache right away.
     InvalidateCache();
   }
 }
 
 void