include/boost/capy/timeout.hpp

100.0% Lines (12/12) 100.0% List of functions (6/6) 100.0% Branches (6/6)
f(x) Functions (6)
Function Calls Lines Branches Blocks
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<boost::capy::io_result<unsigned long> > >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<boost::capy::io_result<unsigned long> >, long, std::ratio<1l, 1000l> >(boost::capy::task<boost::capy::io_result<unsigned long> >, std::chrono::duration<long, std::ratio<1l, 1000l> >) :91 0 100.0% 100.0% boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<int> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<int>, long, std::ratio<1l, 1000l> >(boost::capy::task<int>, std::chrono::duration<long, std::ratio<1l, 1000l> >) :91 0 100.0% 100.0% boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<int> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<int>, long, std::ratio<1l, 1l> >(boost::capy::task<int>, std::chrono::duration<long, std::ratio<1l, 1l> >) :91 0 100.0% 100.0% boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, long, std::ratio<1l, 1l> >(boost::capy::task<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::chrono::duration<long, std::ratio<1l, 1l> >) :91 0 100.0% 100.0% boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<void> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<void>, long, std::ratio<1l, 1000l> >(boost::capy::task<void>, std::chrono::duration<long, std::ratio<1l, 1000l> >) :91 0 100.0% 100.0% boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<void> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<void>, long, std::ratio<1l, 1l> >(boost::capy::task<void>, std::chrono::duration<long, std::ratio<1l, 1l> >) :91 0 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
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/capy
8 //
9
10 #ifndef BOOST_CAPY_TIMEOUT_HPP
11 #define BOOST_CAPY_TIMEOUT_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/concept/io_awaitable.hpp>
15 #include <boost/capy/delay.hpp>
16 #include <boost/capy/error.hpp>
17 #include <boost/capy/io_result.hpp>
18 #include <boost/capy/task.hpp>
19 #include <boost/capy/when_any.hpp>
20
21 #include <chrono>
22 #include <system_error>
23 #include <type_traits>
24
25 namespace boost {
26 namespace capy {
27
28 namespace detail {
29
30 template<typename T>
31 struct is_io_result : std::false_type {};
32
33 template<typename... Args>
34 struct is_io_result<io_result<Args...>> : std::true_type {};
35
36 template<typename T>
37 inline constexpr bool is_io_result_v = is_io_result<T>::value;
38
39 } // detail
40
41 /** Race an awaitable against a deadline.
42
43 Starts the awaitable and a timer concurrently. If the
44 awaitable completes first, its result is returned. If the
45 timer fires first, stop is requested for the awaitable and
46 a timeout error is produced.
47
48 @par Return Type
49
50 The return type matches the inner awaitable's result type:
51
52 @li For `io_result<...>` types: returns `io_result` with
53 `ec == error::timeout` and default-initialized values
54 @li For non-void types: throws `std::system_error(error::timeout)`
55 @li For void: throws `std::system_error(error::timeout)`
56
57 @par Precision
58
59 The timeout fires at or after the specified duration.
60
61 @par Cancellation
62
63 If the parent's stop token is activated, the inner awaitable
64 is cancelled normally (not a timeout). The result reflects
65 the inner awaitable's cancellation behavior.
66
67 @par Example
68 @code
69 auto [ec, n] = co_await timeout(sock.read_some(buf), 50ms);
70 if (ec == cond::timeout) {
71 // handle timeout
72 }
73 @endcode
74
75 @tparam A An IoAwaitable whose result type determines
76 how timeouts are reported.
77
78 @param a The awaitable to race against the deadline.
79 @param dur The maximum duration to wait.
80
81 @return `task<awaitable_result_t<A>>`.
82
83 @throws std::system_error with `error::timeout` if the timer
84 fires first and the result type is not `io_result`.
85 Exceptions thrown by the inner awaitable propagate
86 unchanged.
87
88 @see delay, when_any, cond::timeout
89 */
90 template<IoAwaitable A, typename Rep, typename Period>
91
6/6
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<boost::capy::io_result<unsigned long> > >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<boost::capy::io_result<unsigned long> >, long, std::ratio<1l, 1000l> >(boost::capy::task<boost::capy::io_result<unsigned long> >, std::chrono::duration<long, std::ratio<1l, 1000l> >):
✓ Branch 1 taken 1 time.
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<int> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<int>, long, std::ratio<1l, 1000l> >(boost::capy::task<int>, std::chrono::duration<long, std::ratio<1l, 1000l> >):
✓ Branch 1 taken 2 times.
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<int> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<int>, long, std::ratio<1l, 1l> >(boost::capy::task<int>, std::chrono::duration<long, std::ratio<1l, 1l> >):
✓ Branch 1 taken 2 times.
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, long, std::ratio<1l, 1l> >(boost::capy::task<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::chrono::duration<long, std::ratio<1l, 1l> >):
✓ Branch 1 taken 1 time.
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<void> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<void>, long, std::ratio<1l, 1000l> >(boost::capy::task<void>, std::chrono::duration<long, std::ratio<1l, 1000l> >):
✓ Branch 1 taken 1 time.
boost::capy::task<decltype ((((declval<std::decay<boost::capy::task<void> >::type&>)()).await_resume)())> boost::capy::timeout<boost::capy::task<void>, long, std::ratio<1l, 1l> >(boost::capy::task<void>, std::chrono::duration<long, std::ratio<1l, 1l> >):
✓ Branch 1 taken 1 time.
8x auto timeout(A a, std::chrono::duration<Rep, Period> dur)
92 -> task<awaitable_result_t<A>>
93 {
94 using T = awaitable_result_t<A>;
95
96 auto result = co_await when_any(
97 std::move(a), delay(dur));
98
99 if(result.index() == 0)
100 {
101 // Task completed first
102 if constexpr (std::is_void_v<T>)
103 co_return;
104 else
105 co_return std::get<0>(std::move(result));
106 }
107 else
108 {
109 // Timer won
110 if constexpr (detail::is_io_result_v<T>)
111 {
112 T timeout_result{};
113 timeout_result.ec = make_error_code(error::timeout);
114 co_return timeout_result;
115 }
116 else if constexpr (std::is_void_v<T>)
117 {
118 throw std::system_error(
119 make_error_code(error::timeout));
120 }
121 else
122 {
123 throw std::system_error(
124 make_error_code(error::timeout));
125 }
126 }
127 16x }
128
129 } // capy
130 } // boost
131
132 #endif
133