include/boost/corosio/timeout.hpp

100.0% Lines (9/9) 100.0% List of functions (25/25) 48.9% Branches (43/88)
timeout.hpp
f(x) Functions (25)
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 3x 71.4% 50.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::tcp_socket::connect_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::tcp_socket::connect_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 1x 71.4% 50.0% 71.0% auto boost::corosio::timeout<boost::corosio::tcp_socket::wait_awaitable, long long, std::__1::ratio<1l, 1000l>>(boost::corosio::tcp_socket::wait_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 1x 71.4% 50.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::kqueue_t{}>::testReadyInnerCanceledNotRemapped()::ready_canceled_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::timeout_test<boost::corosio::kqueue_t{}>::testReadyInnerCanceledNotRemapped()::ready_canceled_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{}>::testReadyInnerCompletesWithoutSuspend()::ready_awaitable, long long, std::__1::ratio<1l, 1000l>>(boost::corosio::timeout_test<boost::corosio::kqueue_t{}>::testReadyInnerCompletesWithoutSuspend()::ready_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :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 100.0% 71.0% auto boost::corosio::timeout<boost::corosio::timeout_test<boost::corosio::select_t{}>::testReadyInnerCanceledNotRemapped()::ready_canceled_awaitable, long long, std::__1::ratio<1l, 1l>>(boost::corosio::timeout_test<boost::corosio::select_t{}>::testReadyInnerCanceledNotRemapped()::ready_canceled_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 1x 85.7% 47.7% 71.0% auto boost::corosio::timeout<boost::corosio::timeout_test<boost::corosio::select_t{}>::testReadyInnerCompletesWithoutSuspend()::ready_awaitable, long long, std::__1::ratio<1l, 1000l>>(boost::corosio::timeout_test<boost::corosio::select_t{}>::testReadyInnerCompletesWithoutSuspend()::ready_awaitable, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 1x 100.0% 71.0% boost::capy::const_buffer boost::corosio::timeout<auto boost::capy::any_write_stream::write_some<boost::capy::const_buffer>(boost::capy::const_buffer)::awaitable, long long, std::__1::ratio<1l, 1l>>(auto boost::capy::any_write_stream::write_some<boost::capy::const_buffer>(boost::capy::const_buffer)::awaitable, std::__1::ratio::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 2x 100.0% 71.0% boost::capy::mutable_buffer boost::corosio::timeout<auto boost::capy::any_read_stream::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer)::awaitable, long long, std::__1::ratio<1l, 1000l>>(auto boost::capy::any_read_stream::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer)::awaitable, std::__1::ratio::chrono::duration<long long, std::__1::ratio<1l, 1000l>>) :70 2x 100.0% 71.0% boost::capy::mutable_buffer boost::corosio::timeout<auto boost::capy::any_read_stream::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer)::awaitable, long long, std::__1::ratio<1l, 1l>>(auto boost::capy::any_read_stream::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer)::awaitable, std::__1::ratio::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 4x 100.0% 71.0% boost::capy::mutable_buffer boost::corosio::timeout<boost::corosio::detail::timeout_awaitable<auto boost::capy::any_read_stream::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer)::awaitable>, long long, std::__1::ratio<1l, 1l>>(auto boost::capy::any_read_stream::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer)::awaitable, std::__1::ratio::chrono::duration<long long, std::__1::ratio<1l, 1l>>) :70 2x 100.0% 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 2054x [[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
22/44
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 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 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 4 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 2 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 2 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 2 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 2 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 time.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 time.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 time.
✗ Branch 42 not taken.
✓ Branch 43 taken 1 time.
4106x auto ns = dsec(dur) >= dsec((nanoseconds::max)())
77 2x ? (nanoseconds::max)()
78
21/44
✗ Branch 0 not taken.
✓ Branch 1 taken 13 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 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 4 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 2 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 2 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 2 times.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 time.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 time.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 time.
✗ Branch 42 not taken.
✓ Branch 43 taken 1 time.
2052x : dsec(dur) <= dsec((nanoseconds::min)())
79 2x ? (nanoseconds::min)()
80 2050x : duration_cast<nanoseconds>(dur);
81 2054x 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