include/boost/corosio/timeout.hpp

100.0% Lines (9/9) 100.0% List of functions (15/15) 48.2% Branches (27/56)
timeout.hpp
f(x) Functions (15)
Function Calls Lines Branches Blocks
auto boost::corosio::timeout<boost::capy::task<boost::capy::io_result<int>>, long long, std::__1::ratio<1l, 1000l>>(boost::capy::task<boost::capy::io_result<int>>, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::delay_awaitable, int, std::__1::ratio<1l, 1000l>>(boost::corosio::delay_awaitable, std::__1::chrono::duration<int, std::__1::ratio<1l, 1000l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::delay_awaitable, long long, std::__1::ratio<1l, 1000l>>(boost::corosio::delay_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 2007x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::delay_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::delay_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 6x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::delay_awaitable, long long, std::__1::ratio<3600l, 1l>>(boost::corosio::delay_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<3600l, 1l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::delay_awaitable, long, std::__1::ratio<3600l, 1l>>(boost::corosio::delay_awaitable, std::__1::chrono::duration<long, std::__1::ratio<3600l, 1l>>) :70 6x 85.7% 75.0% 85.0% auto boost::corosio::timeout<boost::corosio::detail::timeout_awaitable<boost::corosio::delay_awaitable>, long long, std::__1::ratio<1l, 1l>>(boost::corosio::detail::timeout_awaitable<boost::corosio::delay_awaitable>, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::io_read_stream::read_some_awaitable<boost::capy::mutable_buffer>, long long, std::__1::ratio<1l, 1000l>>(boost::corosio::io_read_stream::read_some_awaitable<boost::capy::mutable_buffer>, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::payload_awaitable, long long, std::__1::ratio<1l, 1000l>>(boost::corosio::payload_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::payload_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::payload_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 2x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::timeout_test<boost::corosio::kqueue_t{}>::testInnerErrorPassesThrough()::erroring_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::timeout_test<boost::corosio::kqueue_t{}>::testInnerErrorPassesThrough()::erroring_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 1x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::timeout_test<boost::corosio::kqueue_t{}>::testInnerExceptionPropagates()::throwing_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::timeout_test<boost::corosio::kqueue_t{}>::testInnerExceptionPropagates()::throwing_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 1x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::timeout_test<boost::corosio::select_t{}>::testInnerErrorPassesThrough()::erroring_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::timeout_test<boost::corosio::select_t{}>::testInnerErrorPassesThrough()::erroring_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 1x 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::timeout_test<boost::corosio::select_t{}>::testInnerExceptionPropagates()::throwing_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::timeout_test<boost::corosio::select_t{}>::testInnerExceptionPropagates()::throwing_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 1x 85.7% 46.4% 71.0% auto boost::corosio::timeout<boost::corosio::delay_awaitable>(boost::corosio::delay_awaitable, std::__1::chrono::time_point<std::__1::chrono::time_point::steady_clock, std::__1::chrono::time_point::duration<long long, std::__1::chrono::ratio<1l, 1000000000l>>>) :103 4x 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
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_TIMEOUT_HPP
11 #define BOOST_COROSIO_TIMEOUT_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14 #include <boost/corosio/detail/timeout_awaitable.hpp>
15 #include <boost/capy/concept/io_awaitable.hpp>
16
17 #include <chrono>
18 #include <type_traits>
19 #include <utility>
20
21 namespace boost::corosio {
22
23 /** Race an io_result-returning awaitable against a deadline.
24
25 Starts the awaitable with an interposed stop token and arms a
26 timer. If the awaitable finishes first, its result is returned
27 as-is (success, error, or exception). If the deadline passes
28 first, the awaitable is cancelled and an `io_result` whose
29 `ec` compares equal to `capy::cond::timeout` (with a
30 default-initialized payload) is produced.
31
32 Exceptions from the inner awaitable always propagate; they are
33 never swallowed by the timer.
34
35 @par Preconditions
36 The awaiting coroutine's executor must belong to an
37 `io_context`; any other execution context terminates with a
38 diagnostic.
39
40 @par Cancellation
41 If the parent's stop token is activated, the inner awaitable
42 is cancelled and its cancellation result is returned. Requesting
43 stop from another thread requires a multi-threaded-capable
44 io_context; a context running in single_threaded mode
45 (auto-enabled at concurrency_hint == 1) does not permit
46 cross-thread cancellation.
47
48 @par Example
49 @code
50 auto [ec, n] = co_await timeout(sock.read_some(buf), 50ms);
51 if (ec == capy::cond::timeout) {
52 // handle timeout
53 }
54 @endcode
55
56 @param a The awaitable to race against the deadline.
57 @param dur The maximum duration to wait, measured from
58 suspension.
59
60 @return An awaitable yielding `io_result` matching the inner
61 awaitable's result type.
62
63 @see delay
64 */
65 template<capy::IoAwaitable A, typename Rep, typename Period>
66 requires detail::is_io_result_v<
67 std::remove_cvref_t<capy::awaitable_result_t<A>>> &&
68 std::is_default_constructible_v<
69 std::remove_cvref_t<capy::awaitable_result_t<A>>>
70 2037x [[nodiscard]] auto timeout(A a, std::chrono::duration<Rep, Period> dur)
71 {
72 using namespace std::chrono;
73 // Narrow reps wrap if nanoseconds::max() is converted into them;
74 // a double comparison clamps safely in both directions.
75 using dsec = duration<double>;
76
14/28
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2007 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 time.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 time.
4072x auto ns = dsec(dur) >= dsec((nanoseconds::max)())
77 2x ? (nanoseconds::max)()
78
13/28
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2007 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 time.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 time.
2035x : dsec(dur) <= dsec((nanoseconds::min)())
79 2x ? (nanoseconds::min)()
80 2033x : duration_cast<nanoseconds>(dur);
81 2037x return detail::timeout_awaitable<A>(std::move(a), ns);
82 }
83
84 /** Race an io_result-returning awaitable against an absolute deadline.
85
86 Behaves as the duration overload with the deadline fixed at
87 `tp` instead of measured from suspension.
88
89 @param a The awaitable to race against the deadline.
90 @param tp The steady-clock time point at which the awaitable
91 is cancelled.
92
93 @return An awaitable yielding `io_result` matching the inner
94 awaitable's result type.
95
96 @see delay
97 */
98 template<capy::IoAwaitable A>
99 requires detail::is_io_result_v<
100 std::remove_cvref_t<capy::awaitable_result_t<A>>> &&
101 std::is_default_constructible_v<
102 std::remove_cvref_t<capy::awaitable_result_t<A>>>
103 4x [[nodiscard]] auto timeout(A a, std::chrono::steady_clock::time_point tp)
104 {
105 4x return detail::timeout_awaitable<A>(std::move(a), tp);
106 }
107
108 } // namespace boost::corosio
109
110 #endif
111