From 80b5bc064a263db5f621dae18e4cd8460bfc0af2 Mon Sep 17 00:00:00 2001 From: liushuai <770722922@qq.com> Date: Fri, 21 Jun 2024 15:54:14 +0800 Subject: [PATCH] Add wait_one_for and wait_one_until api --- asio/include/asio/detail/impl/scheduler.ipp | 4 +-- asio/include/asio/detail/scheduler.hpp | 2 +- asio/include/asio/impl/io_context.hpp | 30 +++++++++++++++++++ asio/include/asio/io_context.hpp | 24 +++++++++++++++ .../cpp11/other_eventloop/with_libuv.cpp | 9 +++--- 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/asio/include/asio/detail/impl/scheduler.ipp b/asio/include/asio/detail/impl/scheduler.ipp index 94c66cab25..8ed241ef3a 100644 --- a/asio/include/asio/detail/impl/scheduler.ipp +++ b/asio/include/asio/detail/impl/scheduler.ipp @@ -230,10 +230,10 @@ std::size_t scheduler::run_one(asio::error_code& ec) return do_run_one(lock, this_thread, ec); } -std::size_t scheduler::wait_event(long usec, asio::error_code &ec) +void scheduler::wait_event(long usec, asio::error_code &ec) { task_->mask_wait_only(); - return wait_one(usec, ec); + wait_one(usec, ec); } std::size_t scheduler::wait_one(long usec, asio::error_code& ec) diff --git a/asio/include/asio/detail/scheduler.hpp b/asio/include/asio/detail/scheduler.hpp index dd682d12e1..c107ac957e 100644 --- a/asio/include/asio/detail/scheduler.hpp +++ b/asio/include/asio/detail/scheduler.hpp @@ -78,7 +78,7 @@ class scheduler ASIO_DECL std::size_t poll_one(asio::error_code& ec); // Wait until timeout, interrupted, or one operation event. - ASIO_DECL std::size_t wait_event(long usec, asio::error_code& ec); + ASIO_DECL void wait_event(long usec, asio::error_code& ec); // Interrupt the event processing loop. ASIO_DECL void stop(); diff --git a/asio/include/asio/impl/io_context.hpp b/asio/include/asio/impl/io_context.hpp index 002b585502..014b636bbf 100644 --- a/asio/include/asio/impl/io_context.hpp +++ b/asio/include/asio/impl/io_context.hpp @@ -106,6 +106,36 @@ std::size_t io_context::run_one_until( return 0; } +template +void io_context::wait_one_for(const chrono::duration& rel_time) +{ + this->wait_one_until(chrono::steady_clock::now() + rel_time); +} + +template +void io_context::wait_one_until( + const chrono::time_point &abs_time) +{ + typename Clock::time_point now = Clock::now(); + while (now < abs_time) { + typename Clock::duration rel_time = abs_time - now; + if (rel_time > chrono::seconds(1)) + rel_time = chrono::seconds(1); + + asio::error_code ec; + impl_.wait_event( + static_cast( + chrono::duration_cast(rel_time).count()), + ec); + asio::detail::throw_error(ec); + + if (impl_.stopped()) + return; + + now = Clock::now(); + } +} + #if !defined(ASIO_NO_DEPRECATED) inline void io_context::reset() diff --git a/asio/include/asio/io_context.hpp b/asio/include/asio/io_context.hpp index 5de125685f..9aa5a8dce3 100644 --- a/asio/include/asio/io_context.hpp +++ b/asio/include/asio/io_context.hpp @@ -482,6 +482,30 @@ class io_context ASIO_DECL count_type poll_one(asio::error_code& ec); #endif // !defined(ASIO_NO_DEPRECATED) + /// Run the io_context object's event processing loop for a specified duration + /// do not execute any handler, just wait. + /** + * The wait_one_for() function blocks until one handler has been dispatched, + * until the io_context has been stopped, or until the specified duration has + * elapsed. + * + * @param rel_time The duration for which the call may block. + */ + template + void wait_one_for(const chrono::duration& rel_time); + + /// Run the io_context object's event processing loop until a specified time + /// do not execute any handler, just wait. + /** + * The wait_one_until() function blocks until one handler has been dispatched, + * until the io_context has been stopped, or until the specified time has + * been reached. + * + * @param abs_time The time point until which the call may block. + */ + template + void wait_one_until(const chrono::time_point& abs_time); + /// Stop the io_context object's event processing loop. /** * This function does not block, but instead simply signals the io_context to diff --git a/asio/src/examples/cpp11/other_eventloop/with_libuv.cpp b/asio/src/examples/cpp11/other_eventloop/with_libuv.cpp index ba9cf9a1ce..504e58b43d 100644 --- a/asio/src/examples/cpp11/other_eventloop/with_libuv.cpp +++ b/asio/src/examples/cpp11/other_eventloop/with_libuv.cpp @@ -2,8 +2,7 @@ #include #include -//#define USE_LOG -#ifdef USE_LOG +#if __has_include("log.h") #include "log.h" #else #define LOG printf @@ -33,6 +32,7 @@ int main() { static std::condition_variable async_done; std::mutex async_done_lock; + uv_async_t async; uv_async_init(loop, &async, [](uv_async_t *handle) { io_context.poll_one(); @@ -42,9 +42,8 @@ int main() { std::thread([&] { for (;;) { LOG("wait_event..."); - asio::error_code ec; - auto &service = asio::use_service(io_context); - service.wait_event(INTMAX_MAX, ec); + io_context.wait_one_for(std::chrono::minutes(1)); + uv_async_send(&async); std::unique_lock lock(async_done_lock); async_done.wait(lock);