21#include "lib/stdcompat/type_traits.h"
22#include "pw_assert/assert.h"
23#include "pw_async2/channel.h"
24#include "pw_async2/context.h"
25#include "pw_async2/future.h"
26#include "pw_async2/poll.h"
27#include "pw_async2/system_time_provider.h"
28#include "pw_async2/time_provider.h"
29#include "pw_async2/value_future.h"
30#include "pw_chrono/system_clock.h"
31#include "pw_function/function.h"
32#include "pw_preprocessor/compiler.h"
33#include "pw_status/status.h"
41 constexpr Poll<> operator()()
const {
return Ready(); }
55 : ready_(std::move(ready_value_fn)) {}
57 constexpr Poll<T> operator()()
const {
58 return Ready<T>(std::in_place_t{}, ready_());
74template <
typename T,
typename ConstantType,
typename CastType = T>
79 const cpp20::remove_cvref_t<ConstantType>& value)
82 cpp20::remove_cvref_t<ConstantType>&& value)
83 : constant_(std::move(value)) {}
85 constexpr Poll<T> operator()()
const {
86 return Ready<T>(std::in_place_t{}, CastType(constant_));
90 cpp20::remove_cvref_t<ConstantType> constant_;
101 std::integral_constant<pw::Status::Code, PW_STATUS_DEADLINE_EXCEEDED>,
125 typename PrimaryFuture,
126 typename TimeoutFuture,
127 typename TimeoutResolution,
128 typename = std::enable_if_t<!std::is_lvalue_reference_v<PrimaryFuture>>,
129 typename = std::enable_if_t<!std::is_lvalue_reference_v<TimeoutFuture>>,
130 typename = std::enable_if_t<!std::is_lvalue_reference_v<TimeoutResolution>>>
133 FutureWithTimeout<T, PrimaryFuture, TimeoutFuture, TimeoutResolution>,
136 is_future_v<PrimaryFuture>,
137 "FutureWithTimeout can only be used when PrimaryFuture is a Future type");
139 is_future_v<TimeoutFuture>,
140 "FutureWithTimeout can only be used when TimeoutFuture is a Future type");
144 TimeoutFuture&& timeout_future,
145 TimeoutResolution&& timeout_resolution)
146 : state_{std::in_place,
147 State{.primary_future = std::move(primary_future),
148 .timeout_future_ = std::move(timeout_future),
149 .timeout_resolution_ = std::move(timeout_resolution)}} {}
158 PW_DASSERT(state_.has_value());
159 auto result = state_->primary_future.Pend(cx);
160 if (result.IsReady()) {
161 return Ready<typename Base::value_type>(std::in_place_t{},
162 std::move(result).value());
165 if (state_->timeout_future_.Pend(cx).IsReady()) {
166 return state_->timeout_resolution_();
172 void DoMarkComplete() { state_.reset(); }
173 [[nodiscard]]
bool DoIsComplete()
const {
return !state_.has_value(); }
176 PrimaryFuture primary_future;
177 TimeoutFuture timeout_future_;
180 std::optional<State> state_;
191 typename PrimaryFuture,
192 typename TimeoutFuture,
193 typename TimeoutResolution>
194auto CreateFutureWithTimeout(PrimaryFuture&& primary_future,
195 TimeoutFuture&& timeout_future,
196 TimeoutResolution&& timeout_resolution)
198 std::decay_t<PrimaryFuture>,
199 std::decay_t<TimeoutFuture>,
200 std::decay_t<TimeoutResolution>> {
202 std::decay_t<PrimaryFuture>,
203 std::decay_t<TimeoutFuture>,
204 std::decay_t<TimeoutResolution>>(
205 std::forward<PrimaryFuture>(primary_future),
206 std::forward<TimeoutFuture>(timeout_future),
207 std::forward<TimeoutResolution>(timeout_resolution));
221 typename PrimaryFuture,
222 typename TimeProvider,
224 int&... kExplicitGuard,
225 typename = std::enable_if_t<!std::is_lvalue_reference_v<PrimaryFuture>>>
226auto Timeout(PrimaryFuture&& primary_future,
227 TimeProvider& time_provider,
230 return CreateFutureWithTimeout<ResultType>(
231 std::forward<PrimaryFuture>(primary_future),
232 time_provider.WaitFor(delay),
233 DeadlineExceededResolution<ResultType>());
248 typename PrimaryFuture,
249 int&... kExplicitGuard,
250 typename = std::enable_if_t<!std::is_lvalue_reference_v<PrimaryFuture>>>
251auto Timeout(PrimaryFuture&& primary_future,
253 using ResultType = Result<typename std::decay_t<PrimaryFuture>::value_type>;
254 return CreateFutureWithTimeout<ResultType>(
255 std::forward<PrimaryFuture>(primary_future),
257 DeadlineExceededResolution<ResultType>());
271template <
typename Clock>
272void TimeoutOr([[maybe_unused]] ValueFuture<void>&& future,
273 [[maybe_unused]] TimeProvider<Clock>& time_provider,
274 [[maybe_unused]]
typename Clock::duration delay) {
275 static_assert(
false,
"ValueFuture<void> cannot be used with TimeoutOr");
290template <
typename PrimaryFuture,
typename Clock,
typename U>
291auto TimeoutOr(PrimaryFuture&& primary_future,
292 TimeProvider<Clock>& time_provider,
293 typename Clock::duration delay,
294 U&& value_or_fn_on_timeout) {
295 using value_type =
typename PrimaryFuture::value_type;
298 std::is_invocable_v<U> || std::is_convertible_v<U, value_type>,
299 "value_or_fn_on_timeout (U) must be callable, or convert to the "
300 "value_type of the primary_future");
302 if constexpr (std::is_invocable_v<U>) {
303 return CreateFutureWithTimeout<value_type>(
304 std::forward<PrimaryFuture>(primary_future),
305 time_provider.WaitFor(delay),
306 ReadyFunctionResultResolution<value_type>(
307 std::forward<U>(value_or_fn_on_timeout)));
308 }
else if constexpr (std::is_convertible_v<U, value_type>) {
309 return CreateFutureWithTimeout<value_type>(
310 std::forward<PrimaryFuture>(primary_future),
311 time_provider.WaitFor(delay),
312 ReadyConstantValueResolution<value_type, U>(
313 std::forward<U>(value_or_fn_on_timeout)));
325 typename PrimaryFuture,
327 int&... kExplicitGuard,
328 typename = std::enable_if_t<!std::is_lvalue_reference_v<PrimaryFuture>>>
329auto TimeoutOr(PrimaryFuture&& primary_future,
332 return TimeoutOr<typename std::decay_t<PrimaryFuture>>(
333 std::forward<PrimaryFuture>(primary_future),
336 std::forward<Args>(args)...);
349template <
typename T,
typename Clock>
350auto TimeoutOrClosed(ReceiveFuture<T>&& future,
351 TimeProvider<Clock>& time_provider,
352 typename Clock::duration delay) {
353 return CreateFutureWithTimeout<std::optional<T>>(
355 time_provider.WaitFor(delay),
356 ReadyConstantValueResolution<std::optional<T>, std::nullopt_t>(
370template <
typename T,
typename Clock>
371auto TimeoutOrClosed(SendFuture<T>&& future,
372 TimeProvider<Clock>& time_provider,
373 typename Clock::duration delay) {
374 return CreateFutureWithTimeout<T>(
376 time_provider.WaitFor(delay),
377 ReadyConstantValueResolution<bool, std::false_type>());
390template <
typename T,
typename Clock>
391auto TimeoutOrClosed(ReserveSendFuture<T>&& future,
392 TimeProvider<Clock>& time_provider,
393 typename Clock::duration delay) {
394 using ResultType =
typename ReserveSendFuture<T>::value_type;
395 return CreateFutureWithTimeout<ResultType>(
397 time_provider.WaitFor(delay),
398 ReadyConstantValueResolution<std::optional<SendReservation<T>>,
399 std::nullopt_t>(std::nullopt));
410 typename PrimaryFuture,
411 int&... kExplicitGuard,
412 typename = std::enable_if_t<!std::is_lvalue_reference_v<PrimaryFuture>>>
413auto TimeoutOrClosed(PrimaryFuture&& primary_future,
415 return TimeoutOrClosed(std::forward<PrimaryFuture>(primary_future),
422template <
typename T,
typename Clock = chrono::SystemClock>
423using ValueFutureWithTimeout =
424 decltype(Timeout(std::declval<ValueFuture<T>&&>(),
425 std::declval<TimeProvider<Clock>&>(),
426 std::declval<typename Clock::duration>()));
434template <
typename T,
typename U,
typename Clock = chrono::SystemClock>
435using ValueFutureWithTimeoutOr =
436 decltype(TimeoutOr(std::declval<ValueFuture<T>&&>(),
437 std::declval<TimeProvider<Clock>&>(),
438 std::declval<typename Clock::duration>(),
439 std::declval<U&&>()));
443template <
typename T,
typename Clock = chrono::SystemClock>
444using SendFutureWithTimeout =
445 decltype(Timeout(std::declval<SendFuture<T>&&>(),
446 std::declval<TimeProvider<Clock>&>(),
447 std::declval<typename Clock::duration>()));
452template <
typename T,
typename Clock = chrono::SystemClock>
453using ReceiveFutureWithTimeout =
454 decltype(Timeout(std::declval<ReceiveFuture<T>&&>(),
455 std::declval<TimeProvider<Clock>&>(),
456 std::declval<typename Clock::duration>()));
461template <
typename T,
typename Clock = chrono::SystemClock>
462using ReserveSendFutureWithTimeout =
463 decltype(Timeout(std::declval<ReserveSendFuture<T>&&>(),
464 std::declval<TimeProvider<Clock>&>(),
465 std::declval<typename Clock::duration>()));
470template <
typename T,
typename Clock = chrono::SystemClock>
471using SendFutureWithTimeoutOrClosed =
472 decltype(TimeoutOrClosed(std::declval<SendFuture<T>&&>(),
473 std::declval<TimeProvider<Clock>&>(),
474 std::declval<typename Clock::duration>()));
479template <
typename T,
typename Clock = chrono::SystemClock>
480using ReceiveFutureWithTimeoutOrClosed =
481 decltype(TimeoutOrClosed(std::declval<ReceiveFuture<T>&&>(),
482 std::declval<TimeProvider<Clock>&>(),
483 std::declval<typename Clock::duration>()));
488template <
typename T,
typename Clock = chrono::SystemClock>
489using ReserveSendFutureWithTimeoutOrClosed =
490 decltype(TimeoutOrClosed(std::declval<ReserveSendFuture<T>&&>(),
491 std::declval<TimeProvider<Clock>&>(),
492 std::declval<typename Clock::duration>()));
497template <
typename FutureType,
typename Clock = chrono::SystemClock>
498using CustomFutureWithTimeout =
499 decltype(Timeout(std::declval<FutureType&&>(),
500 std::declval<TimeProvider<Clock>&>(),
501 std::declval<typename Clock::duration>()));
509template <
typename FutureType,
typename U,
typename Clock = chrono::SystemClock>
510using CustomFutureWithTimeoutOr =
511 decltype(TimeoutOr(std::declval<FutureType&&>(),
512 std::declval<TimeProvider<Clock>&>(),
513 std::declval<typename Clock::duration>(),
514 std::declval<U&&>()));
Definition: future_timeout.h:134
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:255
TimeProvider< chrono::SystemClock > & GetSystemTimeProvider()
Returns a TimeProvider using the "real" SystemClock and SystemTimer.
std::chrono::duration< rep, period > duration
Alias for durations representable with this clock.
Definition: system_clock.h:90
fit::function_impl< function_internal::config::kInlineCallableSize, !function_internal::config::kEnableDynamicAllocation, FunctionType, PW_FUNCTION_DEFAULT_ALLOCATOR_TYPE > Function
Definition: function.h:73
#define PW_NO_UNIQUE_ADDRESS
Definition: compiler.h:297
Definition: future_timeout.h:39
Definition: future_timeout.h:75
Definition: future_timeout.h:51