From d5b6edc9075ef00d95454341ce28e30e88eeb13a Mon Sep 17 00:00:00 2001 From: qicosmos Date: Sat, 4 Oct 2025 16:54:07 +0800 Subject: [PATCH] add unsafe response --- include/rest_rpc/rest_rpc_protocol.hpp | 2 +- include/rest_rpc/rpc_connection.hpp | 27 +++++++++++++---- tests/test_rest_rpc1.cpp | 40 +++++++++++++++++--------- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/include/rest_rpc/rest_rpc_protocol.hpp b/include/rest_rpc/rest_rpc_protocol.hpp index d1852bf..5ce75e6 100644 --- a/include/rest_rpc/rest_rpc_protocol.hpp +++ b/include/rest_rpc/rest_rpc_protocol.hpp @@ -6,7 +6,7 @@ #include #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(_WIN32) #else inline uint64_t htonll(uint64_t value) { return ((uint64_t)htonl(value & 0xFFFFFFFF) << 32) | htonl(value >> 32); diff --git a/include/rest_rpc/rpc_connection.hpp b/include/rest_rpc/rpc_connection.hpp index 4d3b1dd..c3b5ed7 100644 --- a/include/rest_rpc/rpc_connection.hpp +++ b/include/rest_rpc/rpc_connection.hpp @@ -27,10 +27,15 @@ public: auto get_executor(); template - asio::awaitable response(Args &&...args); + asio::awaitable response_s(Args &&...args); template - std::error_code sync_response(Args &&...args); + std::error_code sync_response_s(Args &&...args); + + template + asio::awaitable response(Args &&...args); + + template std::error_code sync_response(Args &&...args); private: rpc_context() = default; @@ -177,12 +182,24 @@ private: // zero or one arguments template -asio::awaitable rpc_context::response(Args &&...args) { +asio::awaitable rpc_context::response_s(Args &&...args) { using args_tuple = typename util::function_traits::return_type; static_assert( std::is_constructible_v, "rpc function return type and response arguments are not match"); + + return response(std::forward(args)...); +} + +template +std::error_code rpc_context::sync_response_s(Args &&...args) { + return sync_wait(conn_->get_executor(), + response_s(std::forward(args)...)); +} + +template +asio::awaitable rpc_context::response(Args &&...args) { if (has_response_) { co_return make_error_code(rpc_errc::has_response); } @@ -193,10 +210,10 @@ asio::awaitable rpc_context::response(Args &&...args) { co_return co_await conn_->response(result); } -template +template std::error_code rpc_context::sync_response(Args &&...args) { return sync_wait(conn_->get_executor(), - response(std::forward(args)...)); + response(std::forward(args)...)); } auto rpc_context::get_executor() { return conn_->get_executor(); } diff --git a/tests/test_rest_rpc1.cpp b/tests/test_rest_rpc1.cpp index 7a1e66d..7a90814 100644 --- a/tests/test_rest_rpc1.cpp +++ b/tests/test_rest_rpc1.cpp @@ -42,11 +42,15 @@ std::string_view echo_sv(std::string_view str) { return str; } template asio::awaitable response(auto ctx) { - auto ec = co_await ctx.template response("test"); + auto ec = co_await ctx.template response_s("test"); if (ec) { REST_LOG_ERROR << "response error: " << ec.message(); } - ec = co_await ctx.template response("test"); + ec = co_await ctx.template response_s("test"); + REST_LOG_ERROR << ec.message(); + CHECK(ec); + + ec = co_await ctx.response("test"); REST_LOG_ERROR << ec.message(); CHECK(ec); } @@ -56,17 +60,20 @@ std::string_view delay_response(std::string_view str) { // set_delay before response in another thread ctx.set_delay(true); - std::thread thd([ctx = std::move(ctx)]() mutable { - std::this_thread::sleep_for(std::chrono::seconds(2)); - // auto ec = ctx.sync_response("it is from a detached thread"); - // if (ec) { - // REST_LOG_ERROR << "response error: " << ec.message(); - // } - auto executor = ctx.get_executor(); - // async_start(executor, response(std::move(ctx))); - asio::co_spawn(executor, response(std::move(ctx)), asio::detached); - }); - thd.detach(); + // std::thread thd([ctx = std::move(ctx)]() mutable { + // std::this_thread::sleep_for(std::chrono::seconds(2)); + // // auto ec = ctx.sync_response("it is from a detached thread"); + // // if (ec) { + // // REST_LOG_ERROR << "response error: " << ec.message(); + // // } + // auto executor = ctx.get_executor(); + // // async_start(executor, response(std::move(ctx))); + // asio::co_spawn(executor, response(std::move(ctx)), asio::detached); + // }); + // thd.detach(); + + auto executor = ctx.get_executor(); + asio::co_spawn(executor, response(std::move(ctx)), asio::detached); // this return value is meaningless, because it will response later, the // return type is important for client, so just return an empty value here. @@ -89,7 +96,7 @@ asio::awaitable no_arg_coro1() { co_return "test"; } -// TODO: handle connection lifetime, client pool, pub/sub +// TODO: client pool, pub/sub asio::awaitable test_router() { rpc_router router; router.register_handler(); @@ -232,6 +239,11 @@ TEST_CASE("test server start") { cl.call_for(std::chrono::minutes(2), "test")); CHECK(result0.ec == rpc_errc::ok); + result0 = + sync_wait(cl.get_executor(), + cl.call_for(std::chrono::minutes(2), "test")); + CHECK(result0.ec == rpc_errc::ok); + auto result = sync_wait(cl.get_executor(), cl.call_for(std::chrono::minutes(2), "test"));