diff --git a/ipc/hal/DaemonRunnables.h b/ipc/hal/DaemonRunnables.h new file mode 100644 index 000000000000..fcb770e9f90d --- /dev/null +++ b/ipc/hal/DaemonRunnables.h @@ -0,0 +1,807 @@ +/* -*- 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 "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) + { + nsRefPtr 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 + } + nsRefPtr runnable = Create(aObj, aMethod, aInitOp); + if (!runnable) { + return; + } + 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(); + } + + nsRefPtr 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) + { + nsRefPtr 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 + } + nsRefPtr runnable = Create(aObj, aMethod, aInitOp); + if (!runnable) { + return; + } + 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); + } + + nsRefPtr 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) + { + nsRefPtr 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 + } + nsRefPtr runnable = Create(aObj, aMethod, aInitOp); + if (!runnable) { + return; + } + 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); + } + + nsRefPtr 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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) + { + nsRefPtr 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) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + 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 diff --git a/ipc/hal/moz.build b/ipc/hal/moz.build index 382856dec0a1..13e01a6dd72f 100644 --- a/ipc/hal/moz.build +++ b/ipc/hal/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla.ipc += [ + 'DaemonRunnables.h', 'DaemonSocket.h', 'DaemonSocketConsumer.h', 'DaemonSocketPDU.h'