From 6eed51d93abfb13a43adcbac769b7c243ce8b937 Mon Sep 17 00:00:00 2001 From: microcai Date: Mon, 21 Oct 2024 00:28:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=80=81=E4=B8=AD=E5=8C=BB?= =?UTF-8?q?=E6=8F=90=E5=87=BA=E7=9A=84=E4=B8=8D=E8=83=BD=20syncAwait=20?= =?UTF-8?q?=E7=84=B6=E5=90=8E=E6=8D=95=E8=8E=B7=E5=BC=82=E5=B8=B8=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=82=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E8=A7=81=20test7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ucoro/awaitable.hpp | 94 ++++++++++++++++++++++++++++++++++++- tests/CMakeLists.txt | 1 + tests/test7/CMakeLists.txt | 6 +++ tests/test7/test.cpp | 29 ++++++++++++ 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 tests/test7/CMakeLists.txt create mode 100644 tests/test7/test.cpp diff --git a/include/ucoro/awaitable.hpp b/include/ucoro/awaitable.hpp index 7768162..ff6bf64 100644 --- a/include/ucoro/awaitable.hpp +++ b/include/ucoro/awaitable.hpp @@ -168,6 +168,22 @@ namespace ucoro template using awaitable_return_type = template_parameter_of; + template + struct exception_with_result + { + using type = std::variant; + }; + + template<> + struct exception_with_result + { + using type = std::variant; + }; + + template + using exception_with_result_t = typename exception_with_result::type; + + } // namespace traits struct debug_coro_promise @@ -433,8 +449,7 @@ namespace ucoro auto detach() { - auto launch_coro = [](awaitable lazy) -> awaitable { co_return co_await std::move(lazy); }; - return launch_coro(std::move(*this)); + return detach(std::any{}); } auto detach(std::any local) @@ -452,6 +467,43 @@ namespace ucoro return launched_coro; } + template + auto detach_with_callback(Function completion_handler) + { + return detach_with_callback(std::any{}, completion_handler); + } + + template + auto detach_with_callback(std::any local, Function completion_handler) + { + auto launched_coro = [](awaitable lazy, auto completion_handler) mutable -> awaitable + { + using result_wrapper = ucoro::traits::exception_with_result_t; + try + { + if constexpr (std::is_void_v) + { + co_await std::move(lazy); + completion_handler(result_wrapper{std::current_exception()}); + } + else + { + completion_handler(result_wrapper{co_await std::move(lazy)}); + } + }catch(...) + { + completion_handler(result_wrapper{std::current_exception()}); + } + }(std::move(*this), std::move(completion_handler)); + + if (local.has_value()) + { + launched_coro.set_local(local); + } + + return launched_coro; + } + std::coroutine_handle current_coro_handle_; }; @@ -463,6 +515,7 @@ namespace ucoro auto result = awaitable{std::coroutine_handle>::from_promise(*this)}; return result; } + } // namespace ucoro ////////////////////////////////////////////////////////////////////////// @@ -614,3 +667,40 @@ auto coro_start(Awaitable&& coro) { return coro.detach(); } + +template +inline T sync_await(ucoro::awaitable lazy) +{ + ucoro::traits::exception_with_result_t result; + lazy.detach_with_callback([&](ucoro::traits::exception_with_result_t result_) + { + result = result_; + }); + + if (std::holds_alternative(result)) + { + std::rethrow_exception(std::get(result)); + } + + if (!std::is_void_v) + return std::get(result); +} + +template +inline T sync_await(ucoro::awaitable lazy, std::any local_) +{ + ucoro::traits::exception_with_result_t result; + + lazy.detach_with_callback(local_, [&](ucoro::traits::exception_with_result_t result_) + { + result = result_; + }); + + if (std::holds_alternative(result)) + { + std::rethrow_exception(std::get(result)); + } + + if (!std::is_void_v) + return std::get(result); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ab9046d..f5fc5d9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,6 +3,7 @@ set_target_properties(ucoro_tests PROPERTIES FOLDER "ucoro_tests") add_subdirectory(test1) add_subdirectory(test2) +add_subdirectory(test7) find_package(Boost 1.60 COMPONENTS thread system atomic) if(Boost_FOUND) diff --git a/tests/test7/CMakeLists.txt b/tests/test7/CMakeLists.txt new file mode 100644 index 0000000..3581364 --- /dev/null +++ b/tests/test7/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(test7 test.cpp) +target_link_libraries(test7 ucoro) + +add_test(NAME test7 COMMAND test7) +set_target_properties(test7 PROPERTIES FOLDER "ucoro_tests") \ No newline at end of file diff --git a/tests/test7/test.cpp b/tests/test7/test.cpp new file mode 100644 index 0000000..9786583 --- /dev/null +++ b/tests/test7/test.cpp @@ -0,0 +1,29 @@ + +#include "ucoro/awaitable.hpp" +#include + +ucoro::awaitable test() +{ + throw std::runtime_error("test throw"); + co_return 1; +} + +ucoro::awaitable coro_compute() +{ + co_return co_await test(); +} + +int main(int argc, char** argv) +{ + try + { + std::string str = "hello"; + sync_await(coro_compute(), str); + } + catch (std::exception& e) + { + std::cerr << "抓到异常" << e.what() << std::endl; + } + + return 0; +}