#ifndef ADAPTERS_BOOST_ASIO_DEADLINE_TIMER_AREQ_H #define ADAPTERS_BOOST_ASIO_DEADLINE_TIMER_AREQ_H #include #include #include #include #include #include #include #include #include namespace adapters::boostAsio { /** Coroutine awaiter: true if the delay elapsed, false if cancelled/aborted. */ class DeadlineTimerAReq { public: struct AsyncState { std::atomic settled{false}; bool timerExpiredNormally = false; std::coroutine_handle<> callerSchedHandle; std::shared_ptr timer; }; DeadlineTimerAReq( boost::asio::io_context &resumeIoContext, const boost::posix_time::milliseconds delay, std::optional> &timerOut) : asyncState(std::make_shared()), resumeIoContext(resumeIoContext) { asyncState->timer = std::make_shared(resumeIoContext); timerOut = asyncState->timer; asyncState->timer->expires_from_now(delay); asyncState->timer->async_wait( [this](const boost::system::error_code &error) { onTimer(error); }); } bool await_ready() const noexcept { return asyncState->settled.load(std::memory_order_acquire); } bool await_suspend(std::coroutine_handle<> caller) noexcept { if (asyncState->settled.load(std::memory_order_acquire)) { return false; } asyncState->callerSchedHandle = caller; return true; } bool await_resume() const noexcept { return asyncState->timerExpiredNormally; } private: void onTimer(const boost::system::error_code &error) { if (asyncState->settled.exchange(true)) { return; } asyncState->timerExpiredNormally = !error; signalSettledAndResumeCaller(); } void signalSettledAndResumeCaller() { std::coroutine_handle<> handle = asyncState->callerSchedHandle; if (!handle) { return; } boost::asio::post(resumeIoContext, handle); } std::shared_ptr asyncState; boost::asio::io_context &resumeIoContext; }; inline auto getDeadlineTimerAReqAwaiter( boost::asio::io_context &ioContext, const boost::posix_time::milliseconds delay) { std::optional> timerOut; return DeadlineTimerAReq(ioContext, delay, timerOut); } inline auto getDeadlineTimerAReqAwaiter( boost::asio::io_context &ioContext, const boost::posix_time::milliseconds delay, std::optional> &timerOut) { return DeadlineTimerAReq(ioContext, delay, timerOut); } } // namespace adapters::boostAsio #endif // ADAPTERS_BOOST_ASIO_DEADLINE_TIMER_AREQ_H