100.00% Lines (8/8)
100.00% Functions (2/2)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2026 Steve Gerbino | 2 | // Copyright (c) 2026 Steve Gerbino | |||||
| 3 | // Copyright (c) 2026 Michael Vandeberg | 3 | // Copyright (c) 2026 Michael Vandeberg | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |||||
| 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/cppalliance/corosio | 8 | // Official repository: https://github.com/cppalliance/corosio | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #ifndef BOOST_COROSIO_TIMEOUT_HPP | 11 | #ifndef BOOST_COROSIO_TIMEOUT_HPP | |||||
| 12 | #define BOOST_COROSIO_TIMEOUT_HPP | 12 | #define BOOST_COROSIO_TIMEOUT_HPP | |||||
| 13 | 13 | |||||||
| 14 | #include <boost/corosio/detail/config.hpp> | 14 | #include <boost/corosio/detail/config.hpp> | |||||
| 15 | #include <boost/corosio/detail/timeout_awaitable.hpp> | 15 | #include <boost/corosio/detail/timeout_awaitable.hpp> | |||||
| 16 | #include <boost/capy/concept/io_awaitable.hpp> | 16 | #include <boost/capy/concept/io_awaitable.hpp> | |||||
| 17 | 17 | |||||||
| 18 | #include <chrono> | 18 | #include <chrono> | |||||
| 19 | #include <type_traits> | 19 | #include <type_traits> | |||||
| 20 | #include <utility> | 20 | #include <utility> | |||||
| 21 | 21 | |||||||
| 22 | namespace boost::corosio { | 22 | namespace boost::corosio { | |||||
| 23 | 23 | |||||||
| 24 | /** Race an io_result-returning awaitable against a deadline. | 24 | /** Race an io_result-returning awaitable against a deadline. | |||||
| 25 | 25 | |||||||
| 26 | Starts the awaitable with an interposed stop token and arms a | 26 | Starts the awaitable with an interposed stop token and arms a | |||||
| 27 | timer. If the awaitable finishes first, its result is returned | 27 | timer. If the awaitable finishes first, its result is returned | |||||
| 28 | as-is (success, error, or exception). If the deadline passes | 28 | as-is (success, error, or exception). If the deadline passes | |||||
| 29 | first, the awaitable is cancelled and an `io_result` whose | 29 | first, the awaitable is cancelled and an `io_result` whose | |||||
| 30 | `ec` compares equal to `capy::cond::timeout` (with a | 30 | `ec` compares equal to `capy::cond::timeout` (with a | |||||
| 31 | default-initialized payload) is produced. | 31 | default-initialized payload) is produced. | |||||
| 32 | 32 | |||||||
| 33 | Exceptions from the inner awaitable always propagate; they are | 33 | Exceptions from the inner awaitable always propagate; they are | |||||
| 34 | never swallowed by the timer. | 34 | never swallowed by the timer. | |||||
| 35 | 35 | |||||||
| 36 | @par Preconditions | 36 | @par Preconditions | |||||
| 37 | The awaiting coroutine's executor must belong to an | 37 | The awaiting coroutine's executor must belong to an | |||||
| 38 | `io_context`; any other execution context terminates with a | 38 | `io_context`; any other execution context terminates with a | |||||
| 39 | diagnostic. | 39 | diagnostic. | |||||
| 40 | 40 | |||||||
| 41 | @par Cancellation | 41 | @par Cancellation | |||||
| 42 | If the parent's stop token is activated, the inner awaitable | 42 | If the parent's stop token is activated, the inner awaitable | |||||
| 43 | is cancelled and its cancellation result is returned. Requesting | 43 | is cancelled and its cancellation result is returned. Requesting | |||||
| 44 | stop from another thread requires a multi-threaded-capable | 44 | stop from another thread requires a multi-threaded-capable | |||||
| 45 | io_context; a context running in single_threaded mode | 45 | io_context; a context running in single_threaded mode | |||||
| 46 | (auto-enabled at concurrency_hint == 1) does not permit | 46 | (auto-enabled at concurrency_hint == 1) does not permit | |||||
| 47 | cross-thread cancellation. | 47 | cross-thread cancellation. | |||||
| 48 | 48 | |||||||
| 49 | @par Example | 49 | @par Example | |||||
| 50 | @par !example timeout | 50 | @par !example timeout | |||||
| 51 | 51 | |||||||
| 52 | @param a The awaitable to race against the deadline. | 52 | @param a The awaitable to race against the deadline. | |||||
| 53 | @param dur The maximum duration to wait, measured from | 53 | @param dur The maximum duration to wait, measured from | |||||
| 54 | suspension. | 54 | suspension. | |||||
| 55 | 55 | |||||||
| 56 | @return An awaitable yielding `io_result` matching the inner | 56 | @return An awaitable yielding `io_result` matching the inner | |||||
| 57 | awaitable's result type. | 57 | awaitable's result type. | |||||
| 58 | 58 | |||||||
| 59 | @see delay | 59 | @see delay | |||||
| 60 | */ | 60 | */ | |||||
| 61 | template<capy::IoAwaitable A, typename Rep, typename Period> | 61 | template<capy::IoAwaitable A, typename Rep, typename Period> | |||||
| 62 | requires detail::is_io_result_v< | 62 | requires detail::is_io_result_v< | |||||
| 63 | - | std::remove_cvref_t<capy::awaitable_result_t<A>>> && | 63 | + | std::remove_cvref_t<capy::awaitable_result_t<A>>> && | |||
| 64 | - | std::is_default_constructible_v< | 64 | + | std::is_default_constructible_v< | |||
| 65 | - | std::remove_cvref_t<capy::awaitable_result_t<A>>> | 65 | + | std::remove_cvref_t<capy::awaitable_result_t<A>>> | |||
| ECB | 66 | - | 2055 | [[nodiscard]] auto timeout(A a, std::chrono::duration<Rep, Period> dur) | 66 | + | [[nodiscard]] auto | |
| HITGNC | 67 | + | 2055 | timeout(A a, std::chrono::duration<Rep, Period> dur) | ||||
| 67 | { | 68 | { | |||||
| 68 | using namespace std::chrono; | 69 | using namespace std::chrono; | |||||
| 69 | // Narrow reps wrap if nanoseconds::max() is converted into them; | 70 | // Narrow reps wrap if nanoseconds::max() is converted into them; | |||||
| 70 | // a double comparison clamps safely in both directions. | 71 | // a double comparison clamps safely in both directions. | |||||
| 71 | using dsec = duration<double>; | 72 | using dsec = duration<double>; | |||||
| HITCBC | 72 | - | 4082 | auto ns = dsec(dur) >= dsec((nanoseconds::max)()) | 73 | + | 2055 | auto ns = dsec(dur) >= dsec((nanoseconds::max)()) ? (nanoseconds::max)() |
| DCB | 73 | - | 4082 | ? (nanoseconds::max)() | ||||
| HITCBC | 74 | 2053 | : dsec(dur) <= dsec((nanoseconds::min)()) | 74 | 2053 | : dsec(dur) <= dsec((nanoseconds::min)()) | ||
| HITCBC | 75 | - | 2053 | ? (nanoseconds::min)() | 75 | + | 2053 | ? (nanoseconds::min)() |
| HITCBC | 76 | - | 2051 | : duration_cast<nanoseconds>(dur); | 76 | + | 2051 | : duration_cast<nanoseconds>(dur); |
| HITCBC | 77 | 4110 | return detail::timeout_awaitable<A>(std::move(a), ns); | 77 | 4110 | return detail::timeout_awaitable<A>(std::move(a), ns); | ||
| 78 | } | 78 | } | |||||
| 79 | 79 | |||||||
| 80 | /** Race an io_result-returning awaitable against an absolute deadline. | 80 | /** Race an io_result-returning awaitable against an absolute deadline. | |||||
| 81 | 81 | |||||||
| 82 | Behaves as the duration overload with the deadline fixed at | 82 | Behaves as the duration overload with the deadline fixed at | |||||
| 83 | `tp` instead of measured from suspension. | 83 | `tp` instead of measured from suspension. | |||||
| 84 | 84 | |||||||
| 85 | @param a The awaitable to race against the deadline. | 85 | @param a The awaitable to race against the deadline. | |||||
| 86 | @param tp The steady-clock time point at which the awaitable | 86 | @param tp The steady-clock time point at which the awaitable | |||||
| 87 | is cancelled. | 87 | is cancelled. | |||||
| 88 | 88 | |||||||
| 89 | @return An awaitable yielding `io_result` matching the inner | 89 | @return An awaitable yielding `io_result` matching the inner | |||||
| 90 | awaitable's result type. | 90 | awaitable's result type. | |||||
| 91 | 91 | |||||||
| 92 | @see delay | 92 | @see delay | |||||
| 93 | */ | 93 | */ | |||||
| 94 | template<capy::IoAwaitable A> | 94 | template<capy::IoAwaitable A> | |||||
| 95 | requires detail::is_io_result_v< | 95 | requires detail::is_io_result_v< | |||||
| 96 | - | std::remove_cvref_t<capy::awaitable_result_t<A>>> && | 96 | + | std::remove_cvref_t<capy::awaitable_result_t<A>>> && | |||
| 97 | - | std::is_default_constructible_v< | 97 | + | std::is_default_constructible_v< | |||
| 98 | - | std::remove_cvref_t<capy::awaitable_result_t<A>>> | 98 | + | std::remove_cvref_t<capy::awaitable_result_t<A>>> | |||
| ECB | 99 | - | 4 | [[nodiscard]] auto timeout(A a, std::chrono::steady_clock::time_point tp) | 99 | + | [[nodiscard]] auto | |
| HITGNC | 100 | + | 4 | timeout(A a, std::chrono::steady_clock::time_point tp) | ||||
| 100 | { | 101 | { | |||||
| HITCBC | 101 | 4 | return detail::timeout_awaitable<A>(std::move(a), tp); | 102 | 4 | return detail::timeout_awaitable<A>(std::move(a), tp); | ||
| 102 | } | 103 | } | |||||
| 103 | 104 | |||||||
| 104 | } // namespace boost::corosio | 105 | } // namespace boost::corosio | |||||
| 105 | 106 | |||||||
| 106 | #endif | 107 | #endif | |||||