From 9953526ae4bbe5908a3330f6bcf6a1af0c669ed1 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Wed, 1 May 2024 20:12:44 +0800 Subject: [PATCH] added noop utility closes #3 --- include/boost/cobalt/detail/generator.hpp | 3 ++ include/boost/cobalt/detail/promise.hpp | 7 +++ include/boost/cobalt/detail/task.hpp | 8 ++++ include/boost/cobalt/generator.hpp | 1 + include/boost/cobalt/noop.hpp | 55 +++++++++++++++++++++++ include/boost/cobalt/promise.hpp | 6 +++ include/boost/cobalt/task.hpp | 2 + test/generator.cpp | 3 ++ test/promise.cpp | 2 +- test/task.cpp | 3 +- 10 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 include/boost/cobalt/noop.hpp diff --git a/include/boost/cobalt/detail/generator.hpp b/include/boost/cobalt/detail/generator.hpp index ff34c819..5d795f6e 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 @@ -92,6 +93,8 @@ struct generator_receiver : generator_receiver_base bool ready() { return exception || result || done; } + generator_receiver(noop n) : result(std::move(n.value)), done(true) {} + generator_receiver() = default; generator_receiver(generator_receiver && lhs) : generator_receiver_base{std::move(lhs.pushed_value)}, diff --git a/include/boost/cobalt/detail/promise.hpp b/include/boost/cobalt/detail/promise.hpp index 9b45aafb..1bf08851 100644 --- a/include/boost/cobalt/detail/promise.hpp +++ b/include/boost/cobalt/detail/promise.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,8 @@ struct promise_value_holder result.emplace(ret); static_cast*>(this)->set_done(); } + constexpr promise_value_holder() = default; + constexpr promise_value_holder(noop value) noexcept(std::is_nothrow_move_constructible_v) : result(std::move(value.value)) {} }; @@ -79,6 +82,9 @@ struct promise_value_holder } inline void return_void(); + + constexpr promise_value_holder() = default; + constexpr promise_value_holder(noop) {} }; @@ -113,6 +119,7 @@ struct promise_receiver : promise_value_holder } promise_receiver() = default; + promise_receiver(noop value) : promise_value_holder(std::move(value)), done(true) {} promise_receiver(promise_receiver && lhs) noexcept : promise_value_holder(std::move(lhs)), exception(std::move(lhs.exception)), done(lhs.done), awaited_from(std::move(lhs.awaited_from)), diff --git a/include/boost/cobalt/detail/task.hpp b/include/boost/cobalt/detail/task.hpp index 8aff2a58..b557e07a 100644 --- a/include/boost/cobalt/detail/task.hpp +++ b/include/boost/cobalt/detail/task.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,9 @@ struct task_value_holder result.emplace(ret); static_cast*>(this)->set_done(); } + + constexpr task_value_holder() noexcept = default; + constexpr task_value_holder(noop n) noexcept(std::is_nothrow_move_constructible_v) : result(std::move(n.value)) {} }; template<> @@ -72,6 +76,9 @@ struct task_value_holder } inline void return_void(); + + constexpr task_value_holder() noexcept = default; + constexpr task_value_holder(noop n) noexcept {} }; @@ -114,6 +121,7 @@ struct task_receiver : task_value_holder promise->signal.emit(ct); } + task_receiver(noop n) : task_value_holder(std::move(n)), done(true) {} task_receiver() = default; task_receiver(task_receiver && lhs) : task_value_holder(std::move(lhs)), diff --git a/include/boost/cobalt/generator.hpp b/include/boost/cobalt/generator.hpp index 06ab1ebf..0c5fbc09 100644 --- a/include/boost/cobalt/generator.hpp +++ b/include/boost/cobalt/generator.hpp @@ -47,6 +47,7 @@ struct [[nodiscard]] generator generator(const generator &) = delete; generator& operator=(const generator &) = delete; + constexpr generator(noop n) : receiver_(std::move(n)){} private: template diff --git a/include/boost/cobalt/noop.hpp b/include/boost/cobalt/noop.hpp new file mode 100644 index 00000000..9c18e7da --- /dev/null +++ b/include/boost/cobalt/noop.hpp @@ -0,0 +1,55 @@ +// +// Copyright (c) 2024 Klemens Morgenstern (klemens.morgenstern@gmx.net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_COBALT_NOOP_HPP +#define BOOST_COBALT_NOOP_HPP + +#include +#include + +namespace boost::cobalt +{ + + +// tag::outline[] +// This is a tag type allowing the creation of promises or generators without creating a coroutine. +template +struct noop +{ + template + constexpr noop(Args && ... args) noexcept(std::is_nothrow_constructible_v) + : value(std::forward(args)...) + { + } + // end::outline[] + T value; + + constexpr static bool await_ready() {return true;} + template + constexpr static void await_suspend(std::coroutine_handle

) {} + constexpr T await_resume() {return std::move(value);} + + // tag::outline[] +}; +// end::outline[] + +template<> struct noop +{ + constexpr static bool await_ready() {return true;} + template + constexpr static void await_suspend(std::coroutine_handle

) {} + constexpr static void await_resume() {} +}; + + +template noop( T &&) -> noop; +template noop(const T & ) -> noop; +noop() -> noop; + +} + +#endif //BOOST_COBALT_NOOP_HPP diff --git a/include/boost/cobalt/promise.hpp b/include/boost/cobalt/promise.hpp index 9107c174..7e3b3019 100644 --- a/include/boost/cobalt/promise.hpp +++ b/include/boost/cobalt/promise.hpp @@ -41,6 +41,10 @@ struct [[nodiscard]] promise // end::outline[] /* tag::outline[] + // Create an already completed promimse + + static promise + // Get the return value. If !ready() this function has undefined behaviour. Return get(); end::outline[] */ @@ -60,6 +64,8 @@ struct [[nodiscard]] promise if (attached_) cancel(); } + + constexpr promise(noop n) : receiver_(std::move(n)), attached_(false) {} private: template friend struct detail::cobalt_promise; diff --git a/include/boost/cobalt/task.hpp b/include/boost/cobalt/task.hpp index f24bde86..3e8105a9 100644 --- a/include/boost/cobalt/task.hpp +++ b/include/boost/cobalt/task.hpp @@ -34,6 +34,8 @@ struct [[nodiscard]] task using promise_type = detail::task_promise; + constexpr task(noop n) : receiver_(std::move(n)){} + private: template friend struct detail::task_promise; diff --git a/test/generator.cpp b/test/generator.cpp index 2bafefc9..ed441afe 100644 --- a/test/generator.cpp +++ b/test/generator.cpp @@ -296,11 +296,14 @@ cobalt::generator detached_push() co_return i; } +cobalt::generator np() {return cobalt::noop(42);} + CO_TEST_CASE(detached_push_) { auto g = detached_push(); co_await g(1); + co_await np(); } BOOST_AUTO_TEST_SUITE_END(); \ No newline at end of file diff --git a/test/promise.cpp b/test/promise.cpp index c1fe8746..7af51306 100644 --- a/test/promise.cpp +++ b/test/promise.cpp @@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(unwind) cobalt::promise return_(std::size_t ms) { - co_return 1234u; + return cobalt::noop(1234); } cobalt::promise return_(std::size_t ms, asio::executor_arg_t, diff --git a/test/task.cpp b/test/task.cpp index d98fb2f3..c01a4282 100644 --- a/test/task.cpp +++ b/test/task.cpp @@ -34,11 +34,12 @@ namespace cobalt::task test0() { - co_return; + return cobalt::noop(); } cobalt::task test2(int i) { + co_await cobalt::noop(); co_await test0(); co_return i; }