Bug 1361164 - Add Get{Current,Main}ThreadEventTarget getters to replace NS_Get{Current,Main}Thread (r=froydnj)
authorBill McCloskey <billm@mozilla.com>
Mon, 22 May 2017 15:12:43 -0700
changeset 412321 a2e617b58eba
parent 412320 5dae479fd477
child 412322 54f926563d9d
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1361164
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 1361164 - Add Get{Current,Main}ThreadEventTarget getters to replace NS_Get{Current,Main}Thread (r=froydnj) We want people to transition to using event targets rather than threads when possible. These getters should make it easier to make that change. MozReview-Commit-ID: 3bN4tRgJjBL
xpcom/threads/LazyIdleThread.cpp
xpcom/threads/nsIThread.idl
xpcom/threads/nsThread.cpp
xpcom/threads/nsThreadUtils.cpp
xpcom/threads/nsThreadUtils.h
--- a/xpcom/threads/LazyIdleThread.cpp
+++ b/xpcom/threads/LazyIdleThread.cpp
@@ -626,9 +626,29 @@ LazyIdleThread::Observe(nsISupports* /* 
   MOZ_ASSERT(mShutdownMethod == AutomaticShutdown,
              "Should not receive notifications if not AutomaticShutdown!");
   MOZ_ASSERT(!strcmp("xpcom-shutdown-threads", aTopic), "Bad topic!");
 
   Shutdown();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+LazyIdleThread::GetEventTarget(nsIEventTarget** aEventTarget)
+{
+  nsCOMPtr<nsIEventTarget> target = this;
+  target.forget(aEventTarget);
+  return NS_OK;
+}
+
+nsIEventTarget*
+LazyIdleThread::EventTarget()
+{
+  return this;
+}
+
+nsISerialEventTarget*
+LazyIdleThread::SerialEventTarget()
+{
+  return this;
+}
+
 } // namespace mozilla
--- a/xpcom/threads/nsIThread.idl
+++ b/xpcom/threads/nsIThread.idl
@@ -9,16 +9,18 @@
 
 %{C++
 #include "mozilla/AlreadyAddRefed.h"
 %}
 
 [ptr] native PRThread(PRThread);
 
 native alreadyAddRefed_nsIIdlePeriod(already_AddRefed<nsIIdlePeriod>);
+native nsIEventTargetPtr(nsIEventTarget*);
+native nsISerialEventTargetPtr(nsISerialEventTarget*);
 
 /**
  * This interface provides a high-level abstraction for an operating system
  * thread.
  *
  * Threads have a built-in event queue, and a thread is an event target that
  * can receive nsIRunnable objects (events) to be processed on the thread.
  *
@@ -159,9 +161,27 @@ interface nsIThread : nsISerialEventTarg
    *
    * @throws NS_ERROR_INVALID_ARG
    *   Indicates that event is null.
    * @throws NS_ERROR_UNEXPECTED
    *   Indicates that the thread is shutting down and has finished processing
    * events, so this event would never run and has not been dispatched.
    */
   [binaryname(IdleDispatchFromScript)] void idleDispatch(in nsIRunnable event);
+
+  /**
+   * Use this attribute to dispatch runnables to the thread. Eventually, the
+   * eventTarget attribute will be the only way to dispatch events to a
+   * thread--nsIThread will no longer inherit from nsIEventTarget.
+   */
+  readonly attribute nsIEventTarget eventTarget;
+
+  /**
+   * A fast C++ getter for the eventTarget.
+   */
+  [noscript,notxpcom] nsIEventTargetPtr EventTarget();
+
+  /**
+   * A fast C++ getter for the eventTarget. It asserts that the thread's event
+   * target is an nsISerialEventTarget and then returns it.
+   */
+  [noscript,notxpcom] nsISerialEventTargetPtr SerialEventTarget();
 };
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -1659,16 +1659,36 @@ nsThread::DoMainThreadSpecificProcessing
 
 #ifdef MOZ_CRASHREPORTER
   if (!ShuttingDown()) {
     SaveMemoryReportNearOOM(ShouldSaveMemoryReport::kMaybeReport);
   }
 #endif
 }
 
+NS_IMETHODIMP
+nsThread::GetEventTarget(nsIEventTarget** aEventTarget)
+{
+  nsCOMPtr<nsIEventTarget> target = this;
+  target.forget(aEventTarget);
+  return NS_OK;
+}
+
+nsIEventTarget*
+nsThread::EventTarget()
+{
+  return this;
+}
+
+nsISerialEventTarget*
+nsThread::SerialEventTarget()
+{
+  return this;
+}
+
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS(nsThread::nsNestedEventTarget, nsIEventTarget)
 
 NS_IMETHODIMP
 nsThread::nsNestedEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
 {
   nsCOMPtr<nsIRunnable> event(aEvent);
--- a/xpcom/threads/nsThreadUtils.cpp
+++ b/xpcom/threads/nsThreadUtils.cpp
@@ -539,16 +539,64 @@ GetCurrentVirtualThread()
 }
 
 PRThread*
 GetCurrentPhysicalThread()
 {
   return PR_GetCurrentThread();
 }
 
+nsIEventTarget*
+GetCurrentThreadEventTarget()
+{
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
+  if (NS_FAILED(rv)) {
+    return nullptr;
+  }
+
+  return thread->EventTarget();
+}
+
+nsIEventTarget*
+GetMainThreadEventTarget()
+{
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
+  if (NS_FAILED(rv)) {
+    return nullptr;
+  }
+
+  return thread->EventTarget();
+}
+
+nsISerialEventTarget*
+GetCurrentThreadSerialEventTarget()
+{
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
+  if (NS_FAILED(rv)) {
+    return nullptr;
+  }
+
+  return thread->SerialEventTarget();
+}
+
+nsISerialEventTarget*
+GetMainThreadSerialEventTarget()
+{
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
+  if (NS_FAILED(rv)) {
+    return nullptr;
+  }
+
+  return thread->SerialEventTarget();
+}
+
 } // namespace mozilla
 
 bool
 nsIEventTarget::IsOnCurrentThread()
 {
   if (mVirtualThread) {
     return mVirtualThread == GetCurrentVirtualThread();
   }
--- a/xpcom/threads/nsThreadUtils.h
+++ b/xpcom/threads/nsThreadUtils.h
@@ -1819,11 +1819,33 @@ GetCurrentPhysicalThread();
 // Returns a "virtual" PRThread that should only be used for comparison with
 // other calls to GetCurrentVirtualThread. Two threads in the same cooperative
 // thread pool will return the same virtual thread. Threads that are not
 // cooperatively scheduled will have their own unique virtual PRThread (which
 // will be equal to their physical PRThread).
 PRThread*
 GetCurrentVirtualThread();
 
+// These functions return event targets that can be used to dispatch to the
+// current or main thread. They can also be used to test if you're on those
+// threads (via IsOnCurrentThread). These functions should be used in preference
+// to the nsIThread-based NS_Get{Current,Main}Thread functions since they will
+// return more useful answers in the case of threads sharing an event loop.
+
+nsIEventTarget*
+GetCurrentThreadEventTarget();
+
+nsIEventTarget*
+GetMainThreadEventTarget();
+
+// These variants of the above functions assert that the given thread has a
+// serial event target (i.e., that it's not part of a thread pool) and returns
+// that.
+
+nsISerialEventTarget*
+GetCurrentThreadSerialEventTarget();
+
+nsISerialEventTarget*
+GetMainThreadSerialEventTarget();
+
 } // namespace mozilla
 
 #endif  // nsThreadUtils_h__