include/boost/corosio/native/native_timer.hpp

94.3% Lines (33/35) 90.0% List of functions (18/20)
native_timer.hpp
f(x) Functions (20)
Function Calls Lines Blocks
boost::corosio::native_timer<boost::corosio::epoll_t{}>::get_impl() :46 5x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::get_impl() :46 5x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_timer<boost::corosio::epoll_t{}>&) :58 5x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_timer<boost::corosio::select_t{}>&) :58 5x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_wait_awaitable::await_ready() const :63 5x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_wait_awaitable::await_ready() const :63 5x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_wait_awaitable::await_resume() const :68 5x 75.0% 57.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_wait_awaitable::await_resume() const :68 5x 75.0% 57.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_wait_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :75 5x 100.0% 84.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_wait_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :75 5x 100.0% 84.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_timer(boost::capy::execution_context&) :100 8x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_timer(boost::capy::execution_context&) :100 8x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_timer<long, std::ratio<1l, 1000l> >(boost::capy::execution_context&, std::chrono::duration<long, std::ratio<1l, 1000l> >) :115 2x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_timer<long, std::ratio<1l, 1000l> >(boost::capy::execution_context&, std::chrono::duration<long, std::ratio<1l, 1000l> >) :115 2x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_timer<boost::corosio::io_context::executor_type>(boost::corosio::io_context::executor_type const&) :134 1x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_timer<boost::corosio::io_context::executor_type>(boost::corosio::io_context::executor_type const&) :134 1x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_timer<boost::corosio::io_context::executor_type, long, std::ratio<1l, 1000l> >(boost::corosio::io_context::executor_type const&, std::chrono::duration<long, std::ratio<1l, 1000l> >) :162 1x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_timer<boost::corosio::io_context::executor_type, long, std::ratio<1l, 1000l> >(boost::corosio::io_context::executor_type const&, std::chrono::duration<long, std::ratio<1l, 1000l> >) :162 1x 100.0% 100.0% boost::corosio::native_timer<boost::corosio::epoll_t{}>::native_timer(boost::corosio::native_timer<boost::corosio::epoll_t{}>&&) :175 0 0.0% 0.0% boost::corosio::native_timer<boost::corosio::select_t{}>::native_timer(boost::corosio::native_timer<boost::corosio::select_t{}>&&) :175 0 0.0% 0.0%
Line 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_NATIVE_NATIVE_TIMER_HPP
11 #define BOOST_COROSIO_NATIVE_NATIVE_TIMER_HPP
12
13 #include <boost/corosio/timer.hpp>
14 #include <boost/corosio/backend.hpp>
15 #include <boost/corosio/detail/timer_service.hpp>
16
17 namespace boost::corosio {
18
19 /** An asynchronous timer with devirtualized wait operations.
20
21 This class template inherits from @ref timer and shadows the
22 `wait` operation with a version that calls the backend
23 implementation directly, allowing the compiler to inline
24 through the entire call chain.
25
26 Non-async operations (`cancel`, `expires_at`, `expires_after`)
27 remain unchanged and dispatch through the compiled library.
28
29 A `native_timer` IS-A `timer` and can be passed to any function
30 expecting `timer&`.
31
32 @tparam Backend A backend tag value (e.g., `epoll`).
33 The timer implementation is backend-independent; the
34 tag selects the concrete impl type for devirtualization.
35
36 @par Thread Safety
37 Same as @ref timer.
38
39 @see timer, epoll_t, iocp_t
40 */
41 template<auto Backend>
42 class native_timer : public timer
43 {
44 using impl_type = detail::timer_service::implementation;
45
46 10x impl_type& get_impl() noexcept
47 {
48 10x return *static_cast<impl_type*>(h_.get());
49 }
50
51 struct native_wait_awaitable
52 {
53 native_timer& self_;
54 std::stop_token token_;
55 mutable std::error_code ec_;
56 detail::continuation_op cont_op_;
57
58 10x explicit native_wait_awaitable(native_timer& self) noexcept
59 10x : self_(self)
60 {
61 10x }
62
63 10x bool await_ready() const noexcept
64 {
65 10x return token_.stop_requested();
66 }
67
68 10x capy::io_result<> await_resume() const noexcept
69 {
70 10x if (token_.stop_requested())
71 return {capy::error::canceled};
72 10x return {ec_};
73 }
74
75 10x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
76 -> std::coroutine_handle<>
77 {
78 10x token_ = env->stop_token;
79 10x cont_op_.cont.h = h;
80 10x auto& impl = self_.get_impl();
81 // Fast path: already expired and not in the heap
82 20x if (impl.heap_index_ == timer::implementation::npos &&
83 20x (impl.expiry_ == (time_point::min)() ||
84 20x impl.expiry_ <= clock_type::now()))
85 {
86 2x ec_ = {};
87 2x auto d = env->executor;
88 2x d.post(cont_op_.cont);
89 2x return std::noop_coroutine();
90 }
91 8x return impl.wait(h, env->executor, std::move(token_), &ec_, &cont_op_.cont);
92 }
93 };
94
95 public:
96 /** Construct a native timer from an execution context.
97
98 @param ctx The execution context that will own this timer.
99 */
100 16x explicit native_timer(capy::execution_context& ctx) : timer(ctx) {}
101
102 /** Construct a native timer with an initial absolute expiry.
103
104 @param ctx The execution context that will own this timer.
105 @param t The initial expiry time point.
106 */
107 native_timer(capy::execution_context& ctx, time_point t) : timer(ctx, t) {}
108
109 /** Construct a native timer with an initial relative expiry.
110
111 @param ctx The execution context that will own this timer.
112 @param d The initial expiry duration relative to now.
113 */
114 template<class Rep, class Period>
115 4x native_timer(
116 capy::execution_context& ctx, std::chrono::duration<Rep, Period> d)
117 4x : timer(ctx, d)
118 {
119 4x }
120
121 /** Construct a native timer from an executor.
122
123 The timer is associated with the executor's context, which must
124 be a corosio io_context.
125
126 @param ex The executor whose context will own this timer.
127
128 @throws std::logic_error if the executor's context is not an
129 io_context.
130 */
131 template<class Ex>
132 requires(!std::same_as<std::remove_cvref_t<Ex>, native_timer>) &&
133 capy::Executor<Ex>
134 2x explicit native_timer(Ex const& ex) : native_timer(ex.context())
135 {
136 2x }
137
138 /** Construct a native timer from an executor with an absolute expiry.
139
140 @param ex The executor whose context will own this timer.
141 @param t The initial expiry time point.
142
143 @throws std::logic_error if the executor's context is not an
144 io_context.
145 */
146 template<class Ex>
147 requires capy::Executor<Ex>
148 native_timer(Ex const& ex, time_point t) : native_timer(ex.context(), t)
149 {
150 }
151
152 /** Construct a native timer from an executor with a relative expiry.
153
154 @param ex The executor whose context will own this timer.
155 @param d The initial expiry duration relative to now.
156
157 @throws std::logic_error if the executor's context is not an
158 io_context.
159 */
160 template<class Ex, class Rep, class Period>
161 requires capy::Executor<Ex>
162 2x native_timer(Ex const& ex, std::chrono::duration<Rep, Period> d)
163 2x : native_timer(ex.context(), d)
164 {
165 2x }
166
167 /** Move construct.
168
169 @param other The timer to move from.
170
171 @pre No awaitables returned by @p other's methods exist.
172 @pre The execution context associated with @p other must
173 outlive this timer.
174 */
175 native_timer(native_timer&&) noexcept = default;
176
177 /** Move assign.
178
179 @param other The timer to move from.
180
181 @pre No awaitables returned by either `*this` or @p other's
182 methods exist.
183 @pre The execution context associated with @p other must
184 outlive this timer.
185 */
186 native_timer& operator=(native_timer&&) noexcept = default;
187
188 native_timer(native_timer const&) = delete;
189 native_timer& operator=(native_timer const&) = delete;
190
191 /** Wait for the timer to expire.
192
193 Calls the backend implementation directly, bypassing virtual
194 dispatch. Otherwise identical to @ref timer::wait.
195
196 @return An awaitable yielding `io_result<>`.
197
198 This timer must outlive the returned awaitable.
199 */
200 10x auto wait()
201 {
202 10x return native_wait_awaitable(*this);
203 }
204 };
205
206 } // namespace boost::corosio
207
208 #endif
209