Bug 1194112. Part 2 - small code refactoring to reduce typing. r=kinetik.
authorJW Wang <jwwang@mozilla.com>
Mon, 24 Aug 2015 10:38:24 +0800
changeset 259019 e55b03747ebd99186aeb3d9ac5eeeb2e9e0af138
parent 259018 2afb1fcf608b57ef00583b419d79677b6a8587fa
child 259020 37fb89797a7f3f7ec50e98fea978939efb2e4ad2
push id29268
push userryanvm@gmail.com
push dateTue, 25 Aug 2015 00:37:23 +0000
treeherdermozilla-central@08015770c9d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1194112
milestone43.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 1194112. Part 2 - small code refactoring to reduce typing. r=kinetik.
dom/media/MediaEventSource.h
--- a/dom/media/MediaEventSource.h
+++ b/dom/media/MediaEventSource.h
@@ -71,27 +71,30 @@ template <>
 struct EventTypeTraits<void> {
   typedef bool ArgType;
 };
 
 /**
  * Test if a method function or lambda accepts one or more arguments.
  */
 template <typename T>
-class TakeArgs {
+class TakeArgsHelper {
   template <typename C> static FalseType test(void(C::*)(), int);
   template <typename C> static FalseType test(void(C::*)() const, int);
   template <typename C> static FalseType test(void(C::*)() volatile, int);
   template <typename C> static FalseType test(void(C::*)() const volatile, int);
   template <typename F> static FalseType test(F&&, decltype(DeclVal<F>()(), 0));
   static TrueType test(...);
 public:
   typedef decltype(test(DeclVal<T>(), 0)) Type;
 };
 
+template <typename T>
+struct TakeArgs : public TakeArgsHelper<T>::Type {};
+
 template <typename T> struct EventTarget;
 
 template <>
 struct EventTarget<nsIEventTarget> {
   static void
   Dispatch(nsIEventTarget* aTarget, already_AddRefed<nsIRunnable>&& aTask) {
     aTarget->Dispatch(Move(aTask), NS_DISPATCH_NORMAL);
   }
@@ -151,25 +154,25 @@ class ListenerHelper {
   };
 
 public:
   ListenerHelper(RevocableToken* aToken, Target* aTarget, const Function& aFunc)
     : mToken(aToken), mTarget(aTarget), mFunction(aFunc) {}
 
   // |F| takes one argument.
   template <typename F, typename T>
-  typename EnableIf<TakeArgs<F>::Type::value, void>::Type
+  typename EnableIf<TakeArgs<F>::value, void>::Type
   Dispatch(const F& aFunc, T&& aEvent) {
     nsCOMPtr<nsIRunnable> r = new R<T>(mToken, aFunc, Forward<T>(aEvent));
     EventTarget<Target>::Dispatch(mTarget.get(), r.forget());
   }
 
   // |F| takes no arguments. Don't bother passing aEvent.
   template <typename F, typename T>
-  typename EnableIf<!TakeArgs<F>::Type::value, void>::Type
+  typename EnableIf<!TakeArgs<F>::value, void>::Type
   Dispatch(const F& aFunc, T&&) {
     const nsRefPtr<RevocableToken>& token = mToken;
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
       // Don't call the listener if it is disconnected.
       if (!token->IsRevoked()) {
         aFunc();
       }
     });
@@ -232,16 +235,19 @@ private:
 /**
  * A generic and thread-safe class to implement the observer pattern.
  */
 template <typename EventType, ListenerMode Mode = ListenerMode::NonExclusive>
 class MediaEventSource {
   static_assert(!IsReference<EventType>::value, "Ref-type not supported!");
   typedef typename detail::EventTypeTraits<EventType>::ArgType ArgType;
 
+  template <typename Method>
+  using TakeArgs = detail::TakeArgs<Method>;
+
   /**
    * Stored by MediaEventSource to send notifications to the listener.
    */
   class Listener {
   public:
     Listener() : mToken(new RevocableToken()) {}
 
     virtual ~Listener() {
@@ -281,29 +287,29 @@ class MediaEventSource {
     MOZ_ASSERT(Mode == ListenerMode::NonExclusive || mListeners.IsEmpty());
     auto l = mListeners.AppendElement();
     l->reset(new ListenerImpl<Target, Function>(aTarget, aFunction));
     return MediaEventListener((*l)->Token());
   }
 
   // |Method| takes one argument.
   template <typename Target, typename This, typename Method>
-  MediaEventListener
-  ConnectInternal(Target* aTarget, This* aThis, Method aMethod, TrueType) {
+  typename EnableIf<TakeArgs<Method>::value, MediaEventListener>::Type
+  ConnectInternal(Target* aTarget, This* aThis, Method aMethod) {
     detail::RawPtr<This> thiz(aThis);
     auto f = [=] (ArgType&& aEvent) {
       (thiz.get()->*aMethod)(Move(aEvent));
     };
     return ConnectInternal(aTarget, f);
   }
 
   // |Method| takes no arguments. Don't bother passing the event data.
   template <typename Target, typename This, typename Method>
-  MediaEventListener
-  ConnectInternal(Target* aTarget, This* aThis, Method aMethod, FalseType) {
+  typename EnableIf<!TakeArgs<Method>::value, MediaEventListener>::Type
+  ConnectInternal(Target* aTarget, This* aThis, Method aMethod) {
     detail::RawPtr<This> thiz(aThis);
     auto f = [=] () {
       (thiz.get()->*aMethod)();
     };
     return ConnectInternal(aTarget, f);
   }
 
 public:
@@ -336,25 +342,23 @@ public:
    * cycle for the pending event could still hold a reference to |aThis|.
    *
    * The caller must call MediaEventListener::Disconnect() to avoid dangling
    * pointers.
    */
   template <typename This, typename Method>
   MediaEventListener
   Connect(AbstractThread* aTarget, This* aThis, Method aMethod) {
-    return ConnectInternal(aTarget, aThis, aMethod,
-      typename detail::TakeArgs<Method>::Type());
+    return ConnectInternal(aTarget, aThis, aMethod);
   }
 
   template <typename This, typename Method>
   MediaEventListener
   Connect(nsIEventTarget* aTarget, This* aThis, Method aMethod) {
-    return ConnectInternal(aTarget, aThis, aMethod,
-      typename detail::TakeArgs<Method>::Type());
+    return ConnectInternal(aTarget, aThis, aMethod);
   }
 
 protected:
   MediaEventSource() : mMutex("MediaEventSource::mMutex") {}
 
   void NotifyInternal(const ArgType& aEvent) {
     MutexAutoLock lock(mMutex);
     for (int32_t i = mListeners.Length() - 1; i >= 0; --i) {