LCOV - code coverage report
Current view: top level - /jenkins/workspace/boost-root/boost/corosio - timer.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 94.4 % 18 17
Test Date: 2026-02-04 16:37:34 Functions: 100.0 % 10 10

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
       3              : //
       4              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6              : //
       7              : // Official repository: https://github.com/cppalliance/corosio
       8              : //
       9              : 
      10              : #ifndef BOOST_COROSIO_TIMER_HPP
      11              : #define BOOST_COROSIO_TIMER_HPP
      12              : 
      13              : #include <boost/corosio/detail/config.hpp>
      14              : #include <boost/corosio/detail/except.hpp>
      15              : #include <boost/corosio/io_object.hpp>
      16              : #include <boost/capy/io_result.hpp>
      17              : #include <boost/capy/error.hpp>
      18              : #include <boost/capy/ex/executor_ref.hpp>
      19              : #include <boost/capy/ex/execution_context.hpp>
      20              : #include <boost/capy/concept/executor.hpp>
      21              : #include <system_error>
      22              : 
      23              : #include <chrono>
      24              : #include <concepts>
      25              : #include <coroutine>
      26              : #include <stop_token>
      27              : #include <type_traits>
      28              : 
      29              : namespace boost::corosio {
      30              : 
      31              : /** An asynchronous timer for coroutine I/O.
      32              : 
      33              :     This class provides asynchronous timer operations that return
      34              :     awaitable types. The timer can be used to schedule operations
      35              :     to occur after a specified duration or at a specific time point.
      36              : 
      37              :     Each timer operation participates in the affine awaitable protocol,
      38              :     ensuring coroutines resume on the correct executor.
      39              : 
      40              :     @par Thread Safety
      41              :     Distinct objects: Safe.@n
      42              :     Shared objects: Unsafe. A timer must not have concurrent wait
      43              :     operations.
      44              : 
      45              :     @par Semantics
      46              :     Wraps platform timer facilities via the io_context reactor.
      47              :     Operations dispatch to OS timer APIs (timerfd, IOCP timers,
      48              :     kqueue EVFILT_TIMER).
      49              : */
      50              : class BOOST_COROSIO_DECL timer : public io_object
      51              : {
      52              :     struct wait_awaitable
      53              :     {
      54              :         timer& t_;
      55              :         std::stop_token token_;
      56              :         mutable std::error_code ec_;
      57              : 
      58         5364 :         explicit wait_awaitable(timer& t) noexcept : t_(t) {}
      59              : 
      60         5364 :         bool await_ready() const noexcept
      61              :         {
      62         5364 :             return token_.stop_requested();
      63              :         }
      64              : 
      65         5364 :         capy::io_result<> await_resume() const noexcept
      66              :         {
      67         5364 :             if (token_.stop_requested())
      68            0 :                 return {capy::error::canceled};
      69         5364 :             return {ec_};
      70              :         }
      71              : 
      72              :         template<typename Ex>
      73              :         auto await_suspend(
      74              :             std::coroutine_handle<> h,
      75              :             Ex const& ex) -> std::coroutine_handle<>
      76              :         {
      77              :             t_.get().wait(h, ex, token_, &ec_);
      78              :             return std::noop_coroutine();
      79              :         }
      80              : 
      81              :         template<typename Ex>
      82         5364 :         auto await_suspend(
      83              :             std::coroutine_handle<> h,
      84              :             Ex const& ex,
      85              :             std::stop_token token) -> std::coroutine_handle<>
      86              :         {
      87         5364 :             token_ = std::move(token);
      88         5364 :             t_.get().wait(h, ex, token_, &ec_);
      89         5364 :             return std::noop_coroutine();
      90              :         }
      91              :     };
      92              : 
      93              : public:
      94              :     struct timer_impl : io_object_impl
      95              :     {
      96              :         virtual void wait(
      97              :             std::coroutine_handle<>,
      98              :             capy::executor_ref,
      99              :             std::stop_token,
     100              :             std::error_code*) = 0;
     101              :     };
     102              : 
     103              : public:
     104              :     /// The clock type used for time operations.
     105              :     using clock_type = std::chrono::steady_clock;
     106              : 
     107              :     /// The time point type for absolute expiry times.
     108              :     using time_point = clock_type::time_point;
     109              : 
     110              :     /// The duration type for relative expiry times.
     111              :     using duration = clock_type::duration;
     112              : 
     113              :     /** Destructor.
     114              : 
     115              :         Cancels any pending operations and releases timer resources.
     116              :     */
     117              :     ~timer();
     118              : 
     119              :     /** Construct a timer from an execution context.
     120              : 
     121              :         @param ctx The execution context that will own this timer.
     122              :     */
     123              :     explicit timer(capy::execution_context& ctx);
     124              : 
     125              :     /** Move constructor.
     126              : 
     127              :         Transfers ownership of the timer resources.
     128              : 
     129              :         @param other The timer to move from.
     130              :     */
     131              :     timer(timer&& other) noexcept;
     132              : 
     133              :     /** Move assignment operator.
     134              : 
     135              :         Closes any existing timer and transfers ownership.
     136              :         The source and destination must share the same execution context.
     137              : 
     138              :         @param other The timer to move from.
     139              : 
     140              :         @return Reference to this timer.
     141              : 
     142              :         @throws std::logic_error if the timers have different execution contexts.
     143              :     */
     144              :     timer& operator=(timer&& other);
     145              : 
     146              :     timer(timer const&) = delete;
     147              :     timer& operator=(timer const&) = delete;
     148              : 
     149              :     /** Cancel any pending asynchronous operations.
     150              : 
     151              :         All outstanding operations complete with an error code that
     152              :         compares equal to `capy::cond::canceled`.
     153              :     */
     154              :     void cancel();
     155              : 
     156              :     /** Get the timer's expiry time as an absolute time.
     157              : 
     158              :         @return The expiry time point. If no expiry has been set,
     159              :             returns a default-constructed time_point.
     160              :     */
     161              :     time_point expiry() const;
     162              : 
     163              :     /** Set the timer's expiry time as an absolute time.
     164              : 
     165              :         Any pending asynchronous wait operations will be cancelled.
     166              : 
     167              :         @param t The expiry time to be used for the timer.
     168              :     */
     169              :     void expires_at(time_point t);
     170              : 
     171              :     /** Set the timer's expiry time relative to now.
     172              : 
     173              :         Any pending asynchronous wait operations will be cancelled.
     174              : 
     175              :         @param d The expiry time relative to now.
     176              :     */
     177              :     void expires_after(duration d);
     178              : 
     179              :     /** Set the timer's expiry time relative to now.
     180              : 
     181              :         This is a convenience overload that accepts any duration type
     182              :         and converts it to the timer's native duration type.
     183              : 
     184              :         @param d The expiry time relative to now.
     185              :     */
     186              :     template<class Rep, class Period>
     187         5378 :     void expires_after(std::chrono::duration<Rep, Period> d)
     188              :     {
     189         5378 :         expires_after(std::chrono::duration_cast<duration>(d));
     190         5378 :     }
     191              : 
     192              :     /** Wait for the timer to expire.
     193              : 
     194              :         The operation supports cancellation via `std::stop_token` through
     195              :         the affine awaitable protocol. If the associated stop token is
     196              :         triggered, the operation completes immediately with an error
     197              :         that compares equal to `capy::cond::canceled`.
     198              : 
     199              :         @par Example
     200              :         @code
     201              :         timer t(ctx);
     202              :         t.expires_after(std::chrono::seconds(5));
     203              :         auto [ec] = co_await t.wait();
     204              :         if (ec == capy::cond::canceled)
     205              :         {
     206              :             // Cancelled via stop_token or cancel()
     207              :             co_return;
     208              :         }
     209              :         if (ec)
     210              :         {
     211              :             // Handle other errors
     212              :             co_return;
     213              :         }
     214              :         // Timer expired
     215              :         @endcode
     216              : 
     217              :         @return An awaitable that completes with `io_result<>`.
     218              :             Returns success (default error_code) when the timer expires,
     219              :             or an error code on failure. Compare against error conditions
     220              :             (e.g., `ec == capy::cond::canceled`) rather than error codes.
     221              : 
     222              :         @par Preconditions
     223              :         The timer must have an expiry time set via expires_at() or
     224              :         expires_after().
     225              :     */
     226         5364 :     auto wait()
     227              :     {
     228         5364 :         return wait_awaitable(*this);
     229              :     }
     230              : 
     231              : private:
     232        16187 :     timer_impl& get() const noexcept
     233              :     {
     234        16187 :         return *static_cast<timer_impl*>(impl_);
     235              :     }
     236              : };
     237              : 
     238              : } // namespace boost::corosio
     239              : 
     240              : #endif
        

Generated by: LCOV version 2.3