diff --git a/doc/reference/detached.adoc b/doc/reference/detached.adoc index 2fb65197..6ab5f189 100644 --- a/doc/reference/detached.adoc +++ b/doc/reference/detached.adoc @@ -101,4 +101,4 @@ The thread detached has the following properties. - <> - <> - <> - +- <> diff --git a/doc/reference/promise.adoc b/doc/reference/promise.adoc index 83cc3185..4f0c125c 100644 --- a/doc/reference/promise.adoc +++ b/doc/reference/promise.adoc @@ -83,4 +83,4 @@ The coroutine promise (`promise::promise_type`) has the following properties. - <> - <> - <> - +- <> diff --git a/doc/reference/task.adoc b/doc/reference/task.adoc index 13651a4b..560bdefb 100644 --- a/doc/reference/task.adoc +++ b/doc/reference/task.adoc @@ -62,6 +62,7 @@ The task promise has the following properties. - <> - <> - <> +- <> [#use_task] === use_task diff --git a/doc/reference/this_coro.adoc b/doc/reference/this_coro.adoc index 6a82f7e4..e8369aa1 100644 --- a/doc/reference/this_coro.adoc +++ b/doc/reference/this_coro.adoc @@ -59,6 +59,22 @@ struct my_promise : cobalt::enable_await_executor NOTE: If available the executor gets used by <> +[#enable_await_deferred] +=== Await deferred + +Your coroutine promises can inherit `enable_await_deferred` so that +a single signature `asio::deferred` in a `co_await` expression. + +Since `asio::deferred` is now the default completion token, +this allows below code without specifying any completion token or other specialization. + +[source,cpp] +---- +asio::steady_timer t{co_await cobalt::this_coro::executor}; +co_await t.async_wait(); +---- + + [#promise_memory_resource_base] === Memory resource base diff --git a/doc/reference/thread.adoc b/doc/reference/thread.adoc index eb00f2c5..1d30e369 100644 --- a/doc/reference/thread.adoc +++ b/doc/reference/thread.adoc @@ -81,4 +81,5 @@ The thread promise has the following properties. - <> - <> - <> +- <> diff --git a/include/boost/cobalt/detail/detached.hpp b/include/boost/cobalt/detail/detached.hpp index 2ab5e276..0c215c7d 100644 --- a/include/boost/cobalt/detail/detached.hpp +++ b/include/boost/cobalt/detail/detached.hpp @@ -12,12 +12,10 @@ #include #include #include +#include #include - - - #include #include @@ -39,13 +37,15 @@ struct detached_promise promise_throw_if_cancelled_base, enable_awaitables, enable_await_allocator, - enable_await_executor + enable_await_executor, + enable_await_deferred { using promise_cancellation_base::await_transform; using promise_throw_if_cancelled_base::await_transform; using enable_awaitables::await_transform; using enable_await_allocator::await_transform; using enable_await_executor::await_transform; + using enable_await_deferred::await_transform; [[nodiscard]] detached get_return_object(); diff --git a/include/boost/cobalt/detail/generator.hpp b/include/boost/cobalt/detail/generator.hpp index 6adc29e2..1e0e2d3a 100644 --- a/include/boost/cobalt/detail/generator.hpp +++ b/include/boost/cobalt/detail/generator.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -347,13 +348,15 @@ struct generator_promise promise_throw_if_cancelled_base, enable_awaitables>, enable_await_allocator>, - enable_await_executor< generator_promise> + enable_await_executor< generator_promise>, + enable_await_deferred { using promise_cancellation_base::await_transform; using promise_throw_if_cancelled_base::await_transform; using enable_awaitables>::await_transform; using enable_await_allocator>::await_transform; using enable_await_executor>::await_transform; + using enable_await_deferred::await_transform; [[nodiscard]] generator get_return_object() { diff --git a/include/boost/cobalt/detail/main.hpp b/include/boost/cobalt/detail/main.hpp index 1f2ae37c..b73519ea 100644 --- a/include/boost/cobalt/detail/main.hpp +++ b/include/boost/cobalt/detail/main.hpp @@ -9,9 +9,9 @@ #define BOOST_DETAIL_COBALT_MAIN_HPP #include +#include #include - #include @@ -41,7 +41,8 @@ struct main_promise : signal_helper, promise_throw_if_cancelled_base, enable_awaitables, enable_await_allocator, - enable_await_executor + enable_await_executor, + enable_await_deferred { main_promise(int, char **) : promise_cancellation_base( signal_helper::signal.slot(), asio::enable_total_cancellation()) @@ -138,8 +139,9 @@ struct main_promise : signal_helper, using enable_awaitables::await_transform; using enable_await_allocator::await_transform; using enable_await_executor::await_transform; + using enable_await_deferred::await_transform; - private: + private: int * result; std::optional> exec; std::optional exec_; diff --git a/include/boost/cobalt/detail/promise.hpp b/include/boost/cobalt/detail/promise.hpp index 1fcb5474..bd6bed99 100644 --- a/include/boost/cobalt/detail/promise.hpp +++ b/include/boost/cobalt/detail/promise.hpp @@ -13,17 +13,16 @@ #include #include #include +#include #include #include - +#include #include - #include #include #include -#include namespace boost::cobalt { @@ -315,6 +314,7 @@ struct cobalt_promise enable_awaitables>, enable_await_allocator>, enable_await_executor>, + enable_await_deferred, cobalt_promise_result { using promise_cancellation_base::await_transform; @@ -322,6 +322,7 @@ struct cobalt_promise using enable_awaitables>::await_transform; using enable_await_allocator>::await_transform; using enable_await_executor>::await_transform; + using enable_await_deferred::await_transform; [[nodiscard]] promise get_return_object() { diff --git a/include/boost/cobalt/detail/task.hpp b/include/boost/cobalt/detail/task.hpp index b557e07a..4b8d900d 100644 --- a/include/boost/cobalt/detail/task.hpp +++ b/include/boost/cobalt/detail/task.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -288,6 +289,7 @@ struct task_promise enable_awaitables>, enable_await_allocator>, enable_await_executor>, + enable_await_deferred, task_promise_result { using promise_cancellation_base::await_transform; @@ -295,6 +297,7 @@ struct task_promise using enable_awaitables>::await_transform; using enable_await_allocator>::await_transform; using enable_await_executor>::await_transform; + using enable_await_deferred::await_transform; [[nodiscard]] task get_return_object() { diff --git a/include/boost/cobalt/detail/thread.hpp b/include/boost/cobalt/detail/thread.hpp index bd73053b..213dc5b9 100644 --- a/include/boost/cobalt/detail/thread.hpp +++ b/include/boost/cobalt/detail/thread.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,8 @@ struct thread_promise : signal_helper_2, promise_throw_if_cancelled_base, enable_awaitables, enable_await_allocator, - enable_await_executor + enable_await_executor, + enable_await_deferred { BOOST_COBALT_DECL thread_promise(); @@ -101,6 +103,7 @@ struct thread_promise : signal_helper_2, using enable_awaitables::await_transform; using enable_await_allocator::await_transform; using enable_await_executor::await_transform; + using enable_await_deferred::await_transform; BOOST_COBALT_DECL boost::cobalt::thread get_return_object(); diff --git a/include/boost/cobalt/op.hpp b/include/boost/cobalt/op.hpp index 642b66e2..a2e16958 100644 --- a/include/boost/cobalt/op.hpp +++ b/include/boost/cobalt/op.hpp @@ -13,6 +13,9 @@ #include #include +#include + + namespace boost::cobalt { @@ -96,9 +99,6 @@ struct op std::rethrow_exception(init_ep); return interpret_as_result(*std::move(result)); } - - - }; awaitable operator co_await() && @@ -164,6 +164,27 @@ struct use_op_t constexpr use_op_t use_op{}; +struct enable_await_deferred +{ + template + auto await_transform(asio::deferred_async_operation op_) + { + struct deferred_op : op + { + asio::deferred_async_operation op_; + deferred_op(asio::deferred_async_operation op_) + : op_(std::move(op_)) {} + + void initiate(cobalt::completion_handler complete) override + { + std::move(op_)(std::move(complete)); + } + }; + + return deferred_op{std::move(op_)}; + } +}; + } namespace boost::asio @@ -207,5 +228,8 @@ struct async_result std::forward(args)...); } }; + + + } #endif //BOOST_COBALT_OP_HPP diff --git a/test/op.cpp b/test/op.cpp index 406b8a9f..ea96bbdd 100644 --- a/test/op.cpp +++ b/test/op.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -200,7 +201,13 @@ CO_TEST_CASE(no_move_from) BOOST_CHECK(p); } +CO_TEST_CASE(deferred) +{ + asio::steady_timer tim{co_await asio::this_coro::executor, std::chrono::milliseconds(10)}; + co_await post_op(co_await asio::this_coro::executor); + std::tuple r = co_await tim.async_wait(asio::as_tuple); +} BOOST_AUTO_TEST_SUITE_END(); \ No newline at end of file