From d7c16fd073ee719a1c72a9d13828b712fc8f5674 Mon Sep 17 00:00:00 2001 From: Alecto Date: Thu, 27 Aug 2020 13:49:48 -0600 Subject: [PATCH] Added suspend_invoke and tags::on_resume --- CMakeLists.txt | 2 +- README.md | 2 +- VERSION | 2 +- include/conduit/async/suspend_invoke.hpp | 42 ++++++++++++++++++++++++ include/conduit/util/tag_types.hpp | 7 +++- main.cpp | 12 ++++++- 6 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 include/conduit/async/suspend_invoke.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d9b0cf..93c99b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0.0) -project(conduit VERSION 0.1.2 LANGUAGES CXX) +project(conduit VERSION 0.2.0 LANGUAGES CXX) option(CONDUIT_Install "Install CMake targets during install step." ON) diff --git a/README.md b/README.md index b127453..4c53506 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ rm -rf conduit On Ubuntu, installation would be as follows: -1. Download [conduit.deb](https://github.com/functionalperez/conduit/releases/download/v0.1.2/conduit_0.1.2-0_all.deb) (This is a download link) +1. Download [conduit.deb](https://github.com/functionalperez/conduit/releases/download/v0.2.0/conduit_0.2.0-0_all.deb) (This is a download link) 2. Go to your downloads folder (`cd ~/Downloads`) 3. Run `sudo apt install ./conduit.deb` (or just double-click the file to open it in the installer) diff --git a/VERSION b/VERSION index d917d3e..0ea3a94 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.2 +0.2.0 diff --git a/include/conduit/async/suspend_invoke.hpp b/include/conduit/async/suspend_invoke.hpp new file mode 100644 index 0000000..a21ab52 --- /dev/null +++ b/include/conduit/async/suspend_invoke.hpp @@ -0,0 +1,42 @@ +#pragma once +#include +#include +#include + +namespace conduit { +// clang-format off +template +concept on_suspend_callback = requires(Func func, std::coroutine_handle<> h) { + { func(h) } -> same_as; +}; + +template +concept on_resume_callback = requires(Func func) { + { func(tags::on_resume) }; +}; +// clang-format on +} // namespace conduit + +namespace conduit::async { +template +struct suspend_invoke_container { + [[no_unique_address]] Func on_suspend; +}; + +template +struct suspend_invoke : suspend_invoke_container, + mixin::Resumable> { + using suspend_invoke_container::on_suspend; + using mixin::Resumable>::await_resume; + decltype(auto) await_resume() { + if constexpr (conduit::on_resume_callback) { + return on_suspend(tags::on_resume); + } else { + return; + } + } +}; + +template +suspend_invoke(Func) -> suspend_invoke; +} // namespace conduit::async \ No newline at end of file diff --git a/include/conduit/util/tag_types.hpp b/include/conduit/util/tag_types.hpp index 7e668b7..7d3d190 100644 --- a/include/conduit/util/tag_types.hpp +++ b/include/conduit/util/tag_types.hpp @@ -2,6 +2,11 @@ #include namespace conduit::tags { +struct on_resume_t { + explicit on_resume_t() = default; +}; +constexpr auto on_resume = on_resume_t(); + struct get_promise_t { explicit get_promise_t() = default; }; @@ -30,4 +35,4 @@ struct nothing_t { }; constexpr auto nothing = nothing_t(); -} // namespace conduit +} // namespace conduit::tags diff --git a/main.cpp b/main.cpp index d1ec4ac..03f478b 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -72,7 +73,6 @@ future test_generator(std::string on_success) { co_return std::string(begin(g), end(g)); } - future test_on_suspend(std::string on_success) { std::string result; auto f = [](std::coroutine_handle<> h, std::string& result, std::string& on_success) { @@ -112,6 +112,15 @@ future test_source(std::string on_success) { co_return result; } +future test_suspend_invoke(std::string on_success) { + std::string result; + co_await async::suspend_invoke{[&](std::coroutine_handle<> h) { + result = on_success; + h.resume(); + }}; + co_return result; +} + future test_task(std::string on_success) { auto coro = [&](std::string& s) -> task { s = on_success; @@ -133,6 +142,7 @@ coroutine run_tests() { RUN_TEST(test_on_suspend); RUN_TEST(test_recursive_generator); RUN_TEST(test_source); + RUN_TEST(test_suspend_invoke); RUN_TEST(test_task); }