Bug 1187230: Generalize Bluetooth daemon runnables, r=shuang
authorThomas Zimmermann <tdz@users.sourceforge.net>
Mon, 27 Jul 2015 13:33:17 +0200
changeset 286375 c08b1aea386333dbaf5b98a1bbcac4a116c983e8
parent 286339 77bdc7ea8f5e4406087e98ba5a3b6564efe062ed
child 286376 757f394b8d0d1fda7d3c036a0262438420ce4b7c
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshuang
bugs1187230
milestone42.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 1187230: Generalize Bluetooth daemon runnables, r=shuang The new daemon runnables are generalized implementations of the Bluetooth daemon runnables. The code is unchanged, except for name changes and fixes to the coding style.
ipc/hal/DaemonRunnables.h
ipc/hal/moz.build
new file mode 100644
--- /dev/null
+++ b/ipc/hal/DaemonRunnables.h
@@ -0,0 +1,808 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_ipc_DaemonRunnables_h
+#define mozilla_ipc_DaemonRunnables_h
+
+#include "mozilla/unused.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace ipc {
+
+//
+// Result handling
+//
+// The classes of type |DaemonResultRunnable[0..3]| transfer a result
+// handler from the I/O thread to the main thread for execution. Call
+// the methods |Create| and |Dispatch| to create or create-and-dispatch
+// a result runnable.
+//
+// You need to specify the called method. The |Create| and |Dispatch|
+// methods of |DaemonResultRunnable[1..3]| receive an extra argument
+// for initializing the result's arguments. During creation, the result
+// runnable calls the supplied class's call operator with the result's
+// argument. This is where initialization and conversion from backend-
+// specific types is performed.
+//
+
+template <typename Obj, typename Res>
+class DaemonResultRunnable0 final : public nsRunnable
+{
+public:
+  typedef DaemonResultRunnable0<Obj, Res> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aObj, aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp)
+  {
+    if (!aObj) {
+      return; // silently return if no result runnable has been given
+    }
+    nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    ((*mObj).*mMethod)();
+    return NS_OK;
+  }
+
+private:
+  DaemonResultRunnable0(Obj* aObj, Res (Obj::*aMethod)())
+    : mObj(aObj)
+    , mMethod(aMethod)
+  {
+    MOZ_ASSERT(mObj);
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    return aInitOp();
+  }
+
+  nsRefPtr<Obj> mObj;
+  void (Obj::*mMethod)();
+};
+
+template <typename Obj, typename Res, typename Tin1, typename Arg1>
+class DaemonResultRunnable1 final : public nsRunnable
+{
+public:
+  typedef DaemonResultRunnable1<Obj, Res, Tin1, Arg1> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aObj, aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    if (!aObj) {
+      return; // silently return if no result runnable has been given
+    }
+    nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    ((*mObj).*mMethod)(mArg1);
+    return NS_OK;
+  }
+
+private:
+  DaemonResultRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1))
+    : mObj(aObj)
+    , mMethod(aMethod)
+  {
+    MOZ_ASSERT(mObj);
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    return aInitOp(mArg1);
+  }
+
+  nsRefPtr<Obj> mObj;
+  Res (Obj::*mMethod)(Arg1);
+  Tin1 mArg1;
+};
+
+template <typename Obj, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Arg1, typename Arg2, typename Arg3>
+class DaemonResultRunnable3 final : public nsRunnable
+{
+public:
+  typedef DaemonResultRunnable3<Obj, Res,
+                                Tin1, Tin2, Tin3,
+                                Arg1, Arg2, Arg3> SelfType;
+
+  template<typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
+         const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aObj, aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename InitOp>
+  static void
+  Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
+           const InitOp& aInitOp)
+  {
+    if (!aObj) {
+      return; // silently return if no result runnable has been given
+    }
+    nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    ((*mObj).*mMethod)(mArg1, mArg2, mArg3);
+    return NS_OK;
+  }
+
+private:
+  DaemonResultRunnable3(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3))
+    : mObj(aObj)
+    , mMethod(aMethod)
+  {
+    MOZ_ASSERT(mObj);
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    return aInitOp(mArg1, mArg2, mArg3);
+  }
+
+  nsRefPtr<Obj> mObj;
+  Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+};
+
+//
+// Notification handling
+//
+// The classes of type |DaemonNotificationRunnable[0..9]| transfer a
+// notification from the I/O thread to a notification handler on the
+// main thread. Call the methods |Create| and |Dispatch| to create or
+// create-and-dispatch a notification runnable.
+//
+// Like with result runnables, you need to specify the called method.
+// And like with result runnables, the |Create| and |Dispatch| methods
+// of |DaemonNotificationRunnable[1..9]| receive an extra argument
+// for initializing the notification's arguments. During creation, the
+// notification runnable calls the class's call operator with the
+// notification's argument. This is where initialization and conversion
+// from backend-specific types is performed.
+//
+
+template <typename ObjectWrapper, typename Res>
+class DaemonNotificationRunnable0 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable0<ObjectWrapper, Res> SelfType;
+
+  template<typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)();
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable0(Res (ObjectType::*aMethod)())
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    return aInitOp();
+  }
+
+  Res (ObjectType::*mMethod)();
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Arg1=Tin1>
+class DaemonNotificationRunnable1 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable1<ObjectWrapper, Res,
+                                      Tin1, Arg1> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable1(Res (ObjectType::*aMethod)(Arg1))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1);
+  Tin1 mArg1;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2,
+          typename Arg1=Tin1, typename Arg2=Tin2>
+class DaemonNotificationRunnable2 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable2<ObjectWrapper, Res,
+                                      Tin1, Tin2,
+                                      Arg1, Arg2> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable2(
+    Res (ObjectType::*aMethod)(Arg1, Arg2))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2);
+  Tin1 mArg1;
+  Tin2 mArg2;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3>
+class DaemonNotificationRunnable3 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable3<ObjectWrapper, Res,
+                                      Tin1, Tin2, Tin3,
+                                      Arg1, Arg2, Arg3> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable3(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3, typename Tin4,
+          typename Arg1=Tin1, typename Arg2=Tin2,
+          typename Arg3=Tin3, typename Arg4=Tin4>
+class DaemonNotificationRunnable4 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable4<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Arg1, Arg2, Arg3, Arg4> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable4(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+  Tin4 mArg4;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Tin4, typename Tin5,
+          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
+          typename Arg4=Tin4, typename Arg5=Tin5>
+class DaemonNotificationRunnable5 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable5<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Tin5, Arg1, Arg2, Arg3, Arg4, Arg5> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable5(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, mArg5);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+  Tin4 mArg4;
+  Tin5 mArg5;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Tin4, typename Tin5, typename Tin6,
+          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
+          typename Arg4=Tin4, typename Arg5=Tin5, typename Arg6=Tin6>
+class DaemonNotificationRunnable6 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable6<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Tin5, Tin6, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6>
+    SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable6(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+  Tin4 mArg4;
+  Tin5 mArg5;
+  Tin6 mArg6;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Tin4, typename Tin5, typename Tin6,
+          typename Tin7, typename Tin8, typename Tin9,
+          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
+          typename Arg4=Tin4, typename Arg5=Tin5, typename Arg6=Tin6,
+          typename Arg7=Tin7, typename Arg8=Tin8, typename Arg9=Tin9>
+class DaemonNotificationRunnable9 final : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef DaemonNotificationRunnable9<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Tin5, Tin6, Tin7, Tin8, Tin9,
+    Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(
+      Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(
+    Res (ObjectType::*aMethod)(
+      Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      return;
+    }
+    unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
+  }
+
+  NS_IMETHODIMP Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      NS_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4,
+                        mArg5, mArg6, mArg7, mArg8, mArg9);
+    }
+    return NS_OK;
+  }
+
+private:
+  DaemonNotificationRunnable9(
+    Res (ObjectType::*aMethod)(
+      Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9))
+    : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4,
+                          mArg5, mArg6, mArg7, mArg8, mArg9);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(
+    Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+  Tin4 mArg4;
+  Tin5 mArg5;
+  Tin6 mArg6;
+  Tin7 mArg7;
+  Tin8 mArg8;
+  Tin9 mArg9;
+};
+
+}
+}
+
+#endif // mozilla_ipc_DaemonRunnables_h
--- a/ipc/hal/moz.build
+++ b/ipc/hal/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS.mozilla.ipc += [
+    'DaemonRunnables.h',
     'DaemonSocket.h',
     'DaemonSocketConsumer.h',
     'DaemonSocketPDU.h'
 ]
 
 UNIFIED_SOURCES += [
     'DaemonSocket.cpp',
     'DaemonSocketConsumer.cpp',