/* -*- 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 class DaemonResultRunnable0 final : public nsRunnable { public: typedef DaemonResultRunnable0 SelfType; template static already_AddRefed Create(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aObj, aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp) { if (!aObj) { return; // silently return if no result runnable has been given } RefPtr 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 nsresult Init(const InitOp& aInitOp) { return aInitOp(); } RefPtr mObj; void (Obj::*mMethod)(); }; template class DaemonResultRunnable1 final : public nsRunnable { public: typedef DaemonResultRunnable1 SelfType; template static already_AddRefed Create(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aObj, aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp) { if (!aObj) { return; // silently return if no result runnable has been given } RefPtr 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 nsresult Init(const InitOp& aInitOp) { return aInitOp(mArg1); } RefPtr mObj; Res (Obj::*mMethod)(Arg1); Tin1 mArg1; }; template class DaemonResultRunnable3 final : public nsRunnable { public: typedef DaemonResultRunnable3 SelfType; template static already_AddRefed Create(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aObj, aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template 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 } RefPtr 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 nsresult Init(const InitOp& aInitOp) { return aInitOp(mArg1, mArg2, mArg3); } RefPtr 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 class DaemonNotificationRunnable0 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable0 SelfType; template static already_AddRefed Create(Res (ObjectType::*aMethod)(), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(), const InitOp& aInitOp) { RefPtr 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 nsresult Init(const InitOp& aInitOp) { return aInitOp(); } Res (ObjectType::*mMethod)(); }; template class DaemonNotificationRunnable1 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable1 SelfType; template static already_AddRefed Create(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp) { RefPtr 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 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 class DaemonNotificationRunnable2 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable2 SelfType; template static already_AddRefed Create(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp) { RefPtr 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 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 class DaemonNotificationRunnable3 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable3 SelfType; template static already_AddRefed Create(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), const InitOp& aInitOp) { RefPtr 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 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 class DaemonNotificationRunnable4 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable4 SelfType; template static already_AddRefed Create( Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), const InitOp& aInitOp) { RefPtr 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 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 class DaemonNotificationRunnable5 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable5 SelfType; template static already_AddRefed Create( Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), const InitOp& aInitOp) { RefPtr 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 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 class DaemonNotificationRunnable6 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable6 SelfType; template static already_AddRefed Create( Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), const InitOp& aInitOp) { RefPtr 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 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 class DaemonNotificationRunnable9 final : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; typedef DaemonNotificationRunnable9 SelfType; template static already_AddRefed Create( Res (ObjectType::*aMethod)( Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), const InitOp& aInitOp) { RefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->Init(aInitOp))) { return nullptr; } return runnable.forget(); } template static void Dispatch( Res (ObjectType::*aMethod)( Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), const InitOp& aInitOp) { RefPtr 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 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