Bug 1361259. P5 - fix MediaEventSource::CopyEvent2 which is broken by P2. r=gerald
authorJW Wang <jwwang@mozilla.com>
Sat, 29 Apr 2017 00:17:57 +0800
changeset 355993 f79e3e648100b57899044227624e7f5d874664ab
parent 355992 d0d6b7a2b75d1bf4559534c9f1551510efc977bd
child 355994 6b0024a0be7465056df5d7c713c37205af0ab59b
push id31754
push userkwierso@gmail.com
push dateWed, 03 May 2017 00:28:51 +0000
treeherdermozilla-central@5eaf2d70eded [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1361259
milestone55.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 1361259. P5 - fix MediaEventSource::CopyEvent2 which is broken by P2. r=gerald We avoid passing event data to the listener function to save copies if it doesn't take any arguments at all. MozReview-Commit-ID: 7Hkzxrluemm
dom/media/MediaEventSource.h
--- a/dom/media/MediaEventSource.h
+++ b/dom/media/MediaEventSource.h
@@ -128,29 +128,41 @@ private:
 
 template <typename... As>
 class Listener : public RevocableToken
 {
 public:
   template <typename... Ts>
   void Dispatch(Ts&&... aEvents)
   {
-    DispatchTask(NewRunnableMethod<typename Decay<Ts>::Type&&...>(
-      this, &Listener::Apply, Forward<Ts>(aEvents)...));
+    if (CanTakeArgs()) {
+      DispatchTask(NewRunnableMethod<typename Decay<Ts>::Type&&...>(
+        this, &Listener::ApplyWithArgs, Forward<Ts>(aEvents)...));
+    } else {
+      DispatchTask(NewRunnableMethod(this, &Listener::ApplyWithNoArgs));
+    }
   }
 
 protected:
   virtual ~Listener()
   {
     MOZ_ASSERT(IsRevoked(), "Must disconnect the listener.");
   }
 
 private:
   virtual void DispatchTask(already_AddRefed<nsIRunnable> aTask) = 0;
-  virtual void Apply(As&&... aEvents) = 0;
+
+  // True if the underlying listener function takes non-zero arguments.
+  virtual bool CanTakeArgs() const = 0;
+  // Pass the event data to the underlying listener function. Should be called
+  // only when CanTakeArgs() returns true.
+  virtual void ApplyWithArgs(As&&... aEvents) = 0;
+  // Invoke the underlying listener function. Should be called only when
+  // CanTakeArgs() returns false.
+  virtual void ApplyWithNoArgs() = 0;
 };
 
 /**
  * Store the registered target thread and function so it knows where and to
  * whom to send the event data.
  */
 template <typename Target, typename Function, typename... As>
 class ListenerImpl : public Listener<As...>
@@ -163,37 +175,68 @@ public:
   }
 
 private:
   void DispatchTask(already_AddRefed<nsIRunnable> aTask) override
   {
     EventTarget<Target>::Dispatch(mTarget.get(), Move(aTask));
   }
 
+  bool CanTakeArgs() const override
+  {
+    return TakeArgs<Function>::value;
+  }
+
   // |F| takes one or more arguments.
   template <typename F>
   typename EnableIf<TakeArgs<F>::value, void>::Type
-  ApplyImpl(const F& aFunc, As&&... aEvents)
+  ApplyWithArgsImpl(const F& aFunc, As&&... aEvents)
   {
     aFunc(Move(aEvents)...);
   }
 
-  // |F| takes no arguments. Don't bother passing aEvent.
+  // |F| takes no arguments.
   template <typename F>
   typename EnableIf<!TakeArgs<F>::value, void>::Type
-  ApplyImpl(const F& aFunc, As&&... aEvents)
+  ApplyWithArgsImpl(const F& aFunc, As&&... aEvents)
+  {
+    MOZ_CRASH("Call ApplyWithNoArgs instead.");
+  }
+
+  void ApplyWithArgs(As&&... aEvents) override
+  {
+    MOZ_RELEASE_ASSERT(TakeArgs<Function>::value);
+    // Don't call the listener if it is disconnected.
+    if (!RevocableToken::IsRevoked()) {
+      ApplyWithArgsImpl(mFunction, Move(aEvents)...);
+    }
+  }
+
+  // |F| takes one or more arguments.
+  template <typename F>
+  typename EnableIf<TakeArgs<F>::value, void>::Type
+  ApplyWithNoArgsImpl(const F& aFunc)
+  {
+    MOZ_CRASH("Call ApplyWithArgs instead.");
+  }
+
+  // |F| takes no arguments.
+  template <typename F>
+  typename EnableIf<!TakeArgs<F>::value, void>::Type
+  ApplyWithNoArgsImpl(const F& aFunc)
   {
     aFunc();
   }
 
-  void Apply(As&&... aEvents) override
+  virtual void ApplyWithNoArgs() override
   {
+    MOZ_RELEASE_ASSERT(!TakeArgs<Function>::value);
     // Don't call the listener if it is disconnected.
     if (!RevocableToken::IsRevoked()) {
-      ApplyImpl(mFunction, Move(aEvents)...);
+      ApplyWithNoArgsImpl(mFunction);
     }
   }
 
   const RefPtr<Target> mTarget;
   Function mFunction;
 };
 
 /**