diff --git a/include/cinatra/coro_http_server.hpp b/include/cinatra/coro_http_server.hpp index 74247584..0a71ec28 100644 --- a/include/cinatra/coro_http_server.hpp +++ b/include/cinatra/coro_http_server.hpp @@ -18,11 +18,14 @@ namespace cinatra { class coro_http_server { public: + coro_http_server(asio::io_context &ctx, unsigned short port) + : out_ctx_(&ctx), port_(port), acceptor_(ctx), check_timer_(ctx) {} + coro_http_server(size_t thread_num, unsigned short port) - : pool_(thread_num), + : pool_(std::make_unique(thread_num)), port_(port), - acceptor_(pool_.get_executor()->get_asio_executor()), - check_timer_(pool_.get_executor()->get_asio_executor()) {} + acceptor_(pool_->get_executor()->get_asio_executor()), + check_timer_(pool_->get_executor()->get_asio_executor()) {} ~coro_http_server() { CINATRA_LOG_INFO << "coro_http_server will quit"; @@ -56,9 +59,11 @@ class coro_http_server { auto future = promise.getFuture(); if (ec == std::errc{}) { - thd_ = std::thread([this] { - pool_.run(); - }); + if (out_ctx_ == nullptr) { + thd_ = std::thread([this] { + pool_->run(); + }); + } accept().start([p = std::move(promise)](auto &&res) mutable { if (res.hasError()) { @@ -78,7 +83,7 @@ class coro_http_server { // only call once, not thread safe. void stop() { - if (!thd_.joinable()) { + if (out_ctx_ == nullptr && !thd_.joinable()) { return; } @@ -97,11 +102,17 @@ class coro_http_server { connections_.clear(); } - CINATRA_LOG_INFO << "wait for server's thread-pool finish all work."; - pool_.stop(); - CINATRA_LOG_INFO << "server's thread-pool finished."; - thd_.join(); - CINATRA_LOG_INFO << "stop coro_http_server ok"; + if (out_ctx_ == nullptr) { + CINATRA_LOG_INFO << "wait for server's thread-pool finish all work."; + pool_->stop(); + + CINATRA_LOG_INFO << "server's thread-pool finished."; + thd_.join(); + CINATRA_LOG_INFO << "stop coro_http_server ok"; + } + else { + out_ctx_ = nullptr; + } } // call it after server async_start or sync_start. @@ -191,7 +202,16 @@ class coro_http_server { async_simple::coro::Lazy accept() { for (;;) { - auto executor = pool_.get_executor(); + coro_io::ExecutorWrapper<> *executor; + if (out_ctx_ == nullptr) { + executor = pool_->get_executor(); + } + else { + out_executor_ = std::make_unique>( + out_ctx_->get_executor()); + executor = out_executor_.get(); + } + asio::ip::tcp::socket socket(executor->get_asio_executor()); auto error = co_await coro_io::async_accept(acceptor_, socket); if (error) { @@ -286,7 +306,9 @@ class coro_http_server { } private: - coro_io::io_context_pool pool_; + std::unique_ptr pool_; + asio::io_context *out_ctx_ = nullptr; + std::unique_ptr> out_executor_ = nullptr; uint16_t port_; asio::ip::tcp::acceptor acceptor_; std::thread thd_; diff --git a/tests/test_coro_http_server.cpp b/tests/test_coro_http_server.cpp index 603519c7..c671e1cf 100644 --- a/tests/test_coro_http_server.cpp +++ b/tests/test_coro_http_server.cpp @@ -283,6 +283,35 @@ TEST_CASE("get post") { server.stop(); } +TEST_CASE("use out context") { + asio::io_context out_ctx; + auto work = std::make_unique(out_ctx); + std::thread thd([&] { + out_ctx.run(); + }); + + cinatra::coro_http_server server(out_ctx, 9001); + server.set_http_handler( + "/out_ctx", [](coro_http_request &req, coro_http_response &resp) { + resp.set_status_and_content(status_type::ok, "use out ctx"); + }); + + server.async_start(); + std::this_thread::sleep_for(200ms); + + { + coro_http_client client1{}; + auto result = client1.get("http://127.0.0.1:9001/out_ctx"); + CHECK(result.status == 200); + CHECK(result.resp_body == "use out ctx"); + } + + server.stop(); + + work.reset(); + thd.join(); +} + TEST_CASE("delay reply, server stop, form-urlencode, qureies, throw") { cinatra::coro_http_server server(1, 9001);