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..3b460e7c07 100644 --- a/asio/include/asio/impl/io_context.hpp +++ b/asio/include/asio/impl/io_context.hpp @@ -106,6 +106,31 @@ 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(); + if (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 !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_asio.cpp b/asio/src/examples/cpp11/other_eventloop/with_asio.cpp new file mode 100644 index 0000000000..4dd0288fa1 --- /dev/null +++ b/asio/src/examples/cpp11/other_eventloop/with_asio.cpp @@ -0,0 +1,43 @@ +#include "asio.hpp" + +#if __has_include("log.h") +#include "log.h" +#else +#define LOG printf +#endif + +int main() { + asio::io_context io_context_main; + io_context_main.dispatch([] { LOG("main thread"); }); + + std::thread([&] { + LOG("other thread"); + asio::io_context io_context_other; + + asio::steady_timer asio_timer(io_context_other); + std::function start_asio_timer; + start_asio_timer = [&] { + asio_timer.expires_after(asio::chrono::milliseconds(1000)); + asio_timer.async_wait([&](const asio::error_code &ec) { + LOG("asio Timer fired!"); + start_asio_timer(); + }); + }; + start_asio_timer(); + + for (;;) { + LOG("wait_event..."); + io_context_other.wait_one_for(std::chrono::minutes(1)); + std::promise promise; + io_context_main.dispatch([&] { + io_context_other.poll_one(); + promise.set_value(); + }); + promise.get_future().get(); + } + }).detach(); + + asio::io_context::work work(io_context_main); + io_context_main.run(); + return 0; +} diff --git a/asio/src/examples/cpp11/other_eventloop/with_libuv.cpp b/asio/src/examples/cpp11/other_eventloop/with_libuv.cpp index ba9cf9a1ce..7a58612a9e 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 @@ -13,6 +12,7 @@ int main() { uv_loop_t *loop = uv_default_loop(); static asio::io_context io_context; asio::io_context::work work(io_context); + LOG("main thread\n"); uv_timer_t timer_req; uv_timer_init(loop, &timer_req); @@ -33,6 +33,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(); @@ -41,10 +42,9 @@ 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); + LOG("wait_event...\n"); + io_context.wait_one_for(std::chrono::minutes(1)); + uv_async_send(&async); std::unique_lock lock(async_done_lock); async_done.wait(lock);