mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
Implement async_on for asynchronous execution on a specific executor
* Makes it possible to specify an executor in addition to the arguments passed to async. * The reason why async should not support this directly is that it should be closely modelled to std::async.
This commit is contained in:
parent
fa589a1e95
commit
d72e1bfb86
@ -39,8 +39,8 @@
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
namespace operations {
|
||||
template <typename Callable, typename... Args>
|
||||
auto async(Callable&& callable, Args&&... args) {
|
||||
template <typename Callable, typename Executor, typename... Args>
|
||||
auto async(Callable&& callable, Executor&& executor, Args&&... args) {
|
||||
using result_t =
|
||||
decltype(util::invoke(std::forward<decltype(callable)>(callable),
|
||||
std::forward<decltype(args)>(args)...));
|
||||
@ -49,18 +49,22 @@ auto async(Callable&& callable, Args&&... args) {
|
||||
decltype(base::decoration::invoker_of(identity<result_t>{}))::hint();
|
||||
|
||||
auto continuation = [callable = std::forward<decltype(callable)>(callable),
|
||||
executor = std::forward<decltype(executor)>(executor),
|
||||
args = std::make_tuple(std::forward<decltype(args)>(
|
||||
args)...)](auto&& promise) mutable {
|
||||
|
||||
auto invoker = base::decoration::invoker_of(identity<result_t>{});
|
||||
|
||||
using promise_t = decltype(promise);
|
||||
|
||||
// Invoke the callback
|
||||
traits::unpack(
|
||||
[&](auto&&... args) {
|
||||
[&](auto&&... args) mutable {
|
||||
// Invoke the promise through the dedicated invoker
|
||||
invoker(std::move(callable), std::forward<promise_t>(promise),
|
||||
std::forward<decltype(args)>(args)...);
|
||||
// and through the given executor
|
||||
base::on_executor(std::move(executor), std::move(invoker),
|
||||
std::move(callable),
|
||||
std::forward<promise_t>(promise),
|
||||
std::forward<decltype(args)>(args)...);
|
||||
},
|
||||
std::move(args));
|
||||
};
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#define CONTINUABLE_OPERATIONS_ASYNC_HPP_INCLUDED
|
||||
|
||||
#include <utility>
|
||||
#include <continuable/detail/core/types.hpp>
|
||||
#include <continuable/detail/operations/async.hpp>
|
||||
|
||||
namespace cti {
|
||||
@ -41,6 +42,8 @@ namespace cti {
|
||||
/// Wraps the given callable inside a continuable_base such that it is
|
||||
/// invoked when the asynchronous result is requested to return the result.
|
||||
///
|
||||
/// The async function shall be seen as an equivalent to std::async.
|
||||
///
|
||||
/// The behaviour will be equal as when using make_ready_continuable together
|
||||
/// with continuable_base::then, but async is implemented in
|
||||
/// a more efficient way:
|
||||
@ -53,7 +56,7 @@ namespace cti {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// \param callable The callable type which is invoked on request
|
||||
/// \param callable The callable type which is invoked on request.
|
||||
///
|
||||
/// \param args The arguments which are passed to the callable upon invocation.
|
||||
///
|
||||
@ -65,6 +68,46 @@ namespace cti {
|
||||
template <typename Callable, typename... Args>
|
||||
auto async(Callable&& callable, Args&&... args) {
|
||||
return detail::operations::async(std::forward<Callable>(callable),
|
||||
detail::types::this_thread_executor_tag{},
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Wraps the given callable inside a continuable_base such that it is
|
||||
/// invoked through the given executor when the asynchronous result
|
||||
/// is requested to return the result.
|
||||
///
|
||||
/// The behaviour will be equal as when using make_ready_continuable together
|
||||
/// with continuable_base::then and the given executor but async_on
|
||||
/// is implemented in a more efficient way:
|
||||
/// ```cpp
|
||||
/// auto do_sth() {
|
||||
/// auto executor = [](auto&& work) {
|
||||
/// // Do something with the work here
|
||||
/// std::forward<decltype(work)>(work);
|
||||
/// };
|
||||
///
|
||||
/// return async_on([] {
|
||||
/// do_sth_more();
|
||||
/// return 0;
|
||||
/// }, my_executor);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// \param callable The callable type which is invoked on request.
|
||||
///
|
||||
/// \param executor The executor that is used to dispatch the given callable.
|
||||
///
|
||||
/// \param args The arguments which are passed to the callable upon invocation.
|
||||
///
|
||||
/// \returns A continuable_base which asynchronous result type will
|
||||
/// be computated with the same rules as continuable_base::then .
|
||||
///
|
||||
/// \since 4.0.0
|
||||
///
|
||||
template <typename Callable, typename Executor, typename... Args>
|
||||
auto async_on(Callable&& callable, Executor&& executor, Args&&... args) {
|
||||
return detail::operations::async(std::forward<Callable>(callable),
|
||||
std::forward<Executor>(executor),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
/// \}
|
||||
|
||||
@ -44,3 +44,41 @@ TYPED_TEST(single_dimension_tests, operations_async) {
|
||||
}),
|
||||
CANARY, 2, CANARY);
|
||||
}
|
||||
|
||||
TYPED_TEST(single_dimension_tests, operations_async_on_dropping) {
|
||||
bool invoked = false;
|
||||
auto executor = [&](auto&& work) {
|
||||
EXPECT_FALSE(invoked);
|
||||
invoked = true;
|
||||
(void)work;
|
||||
};
|
||||
|
||||
ASSERT_ASYNC_INCOMPLETION(async_on(
|
||||
[] {
|
||||
FAIL(); //
|
||||
},
|
||||
executor));
|
||||
|
||||
ASSERT_TRUE(invoked);
|
||||
}
|
||||
|
||||
TYPED_TEST(single_dimension_tests, operations_async_on_executor) {
|
||||
bool invoked = false;
|
||||
auto executor = [&](auto&& work) {
|
||||
// We can move the worker object
|
||||
auto local = std::forward<decltype(work)>(work);
|
||||
EXPECT_FALSE(invoked);
|
||||
// We can invoke the worker object
|
||||
std::move(local)();
|
||||
EXPECT_TRUE(invoked);
|
||||
};
|
||||
|
||||
ASSERT_ASYNC_COMPLETION(async_on(
|
||||
[&invoked] {
|
||||
EXPECT_FALSE(invoked);
|
||||
invoked = true;
|
||||
},
|
||||
executor));
|
||||
|
||||
ASSERT_TRUE(invoked);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user