diff --git a/docs/base-package.md b/docs/base-package.md index e165dd2..22b02ea 100644 --- a/docs/base-package.md +++ b/docs/base-package.md @@ -14,7 +14,7 @@ These components can be chained as many times as needed, as long as there is one Note that all components deriving from a single parent will be executed **in the same thread**. -Method calls can be **posted to the event loop** via the `kouta::base::Component::post()` method. This is the core of the event-based architecture, as it allows to defer method execution in a single thread in an efficient manner. +Method calls can be **posted to the event loop** via the `kouta::base::Component::post()` method. This is the core of the event-based architecture, as it allows to defer method execution in a single thread in an efficient manner. In addition, it is also possible to **post calls to lambdas and free functions**. A simple component could be: @@ -42,6 +42,9 @@ public: // Deferred method call comp.post(&MyComponent::print_message, 42); comp.post(&MyComponent::print_message, 546); +comp.post([]() { + std::cout << "This is deferred" << std::endl; +}); ``` ## Root diff --git a/include/kouta/base/component.hpp b/include/kouta/base/component.hpp index 599bfd9..62fb0c6 100644 --- a/include/kouta/base/component.hpp +++ b/include/kouta/base/component.hpp @@ -69,15 +69,15 @@ namespace kouta::base /// @brief Post a function call to the event loop for deferred execution. /// /// @details - /// This allows other components, even those residing in another thread/event loop, to post a functor to this - /// specific component, for example a lambda function. + /// This allows other components, even those residing in another thread/event loop, to post a function to this + /// specific component. /// /// @warning Arguments are **copied** before being passed to the event loop. /// /// @tparam TFuncArgs Types of the arguments that the function accepts. /// @tparam TArgs Types of the arguments provided to the invocation. /// - /// @param[in] functor Functor to invoke invoked. Its signature must match `void(TArgs...)` + /// @param[in] functor Functor to invoke. Its signature must match `void(TArgs...)` /// @param[in] args Arguments to invoke the functor with. template void post(const std::function& functor, TArgs... args) @@ -90,6 +90,21 @@ namespace kouta::base }); } + /// @brief Post a functor call to the event loop for deferred execution. + /// + /// @details + /// This allows other components, even those residing in another thread/event loop, to post a functor to this + /// specific component, for example a lambda. + /// + /// @tparam TFunctor Functor type. + /// + /// @param[in] functor Functor to invoke.s + template + void post(TFunctor&& functor) + { + boost::asio::post(context().get_executor(), functor); + } + private: Component* m_parent; }; diff --git a/tests/base/test-base.cpp b/tests/base/test-base.cpp index adf78db..b64975a 100644 --- a/tests/base/test-base.cpp +++ b/tests/base/test-base.cpp @@ -180,7 +180,11 @@ namespace kouta::tests::base root.post(&RootMock::handler_a, std::uint16_t{42}); root.post(&RootMock::handler_b, -512, "This is a test"); - root.post(&RootMock::handler_c, std::vector{12, 34}); + root.post( + [&root]() + { + root.handler_c(std::vector{12, 34}); + }); } /// @brief Test the behaviour of the event loop when running.