idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
future.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
24#include <idfxx/error.hpp>
25
26#include <chrono>
27#include <functional>
28#include <memory>
29#include <optional>
30#include <type_traits>
31#include <utility>
32
33namespace idfxx {
34
61template<typename T>
62class future {
63public:
65 future() = default;
66
92 template<typename W>
93 requires std::is_invocable_r_v<result<T>, W&, std::optional<std::chrono::milliseconds>>
94 explicit future(W waiter)
95 : _state(std::make_shared<state>(std::move(waiter))) {}
96
111 template<typename W, typename D>
112 requires std::is_invocable_r_v<result<T>, W&, std::optional<std::chrono::milliseconds>> &&
113 std::is_nothrow_invocable_r_v<bool, const D&>
115 : _state(std::make_shared<state>(std::move(waiter), std::move(done_check))) {}
116
124 [[nodiscard]] bool valid() const noexcept { return _state != nullptr; }
125
132 [[nodiscard]] bool done() const noexcept;
133
134#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
145 T wait() const { return unwrap(try_wait()); }
146
159 template<typename Rep, typename Period>
160 T wait_for(const std::chrono::duration<Rep, Period>& timeout) const {
161 return unwrap(try_wait_for(timeout));
162 }
163#endif
164
172 [[nodiscard]] result<T> try_wait() const;
173
184 template<typename Rep, typename Period>
185 [[nodiscard]] result<T> try_wait_for(const std::chrono::duration<Rep, Period>& timeout) const;
186
187private:
189 struct state {
190 std::move_only_function<result<T>(std::optional<std::chrono::milliseconds>)> waiter;
191 std::move_only_function<bool() const noexcept> done_check;
192
194 explicit state(W&& w)
195 : waiter(std::forward<W>(w)) {}
196
197 template<typename W, typename D>
198 state(W&& w, D&& d)
199 : waiter(std::forward<W>(w))
200 , done_check(std::forward<D>(d)) {}
201 };
204 std::shared_ptr<state> _state;
205};
206
207template<typename T>
209 if (!_state) {
210 return true;
211 }
212 if (_state->done_check) {
213 return _state->done_check();
214 }
215 auto r = _state->waiter(std::optional<std::chrono::milliseconds>{std::chrono::milliseconds{0}});
216 return r.has_value();
217}
218
219template<typename T>
221 if (!_state) {
222 if constexpr (std::is_void_v<T>) {
223 return {};
224 } else {
225 return T{};
226 }
227 }
228 return _state->waiter(std::nullopt);
229}
230
231template<typename T>
232template<typename Rep, typename Period>
233result<T> future<T>::try_wait_for(const std::chrono::duration<Rep, Period>& timeout) const {
234 if (!_state) {
235 if constexpr (std::is_void_v<T>) {
236 return {};
237 } else {
238 return T{};
239 }
240 }
241 return _state->waiter(
242 std::optional<std::chrono::milliseconds>{std::chrono::ceil<std::chrono::milliseconds>(timeout)}
243 );
244}
245
246} // namespace idfxx
247
// end of idfxx_core_future // end of idfxx_core
Async completion token.
Definition future.hpp:62
future(W waiter, D done_check)
Constructs a future with an explicit non-blocking done-check.
Definition future.hpp:114
future(W waiter)
Constructs a future from a waiter callable.
Definition future.hpp:94
bool valid() const noexcept
Returns whether this future is associated with an async operation.
Definition future.hpp:124
T wait() const
Blocks until the operation completes.
Definition future.hpp:145
result< T > try_wait_for(const std::chrono::duration< Rep, Period > &timeout) const
Blocks until the operation completes or the timeout expires.
Definition future.hpp:233
result< T > try_wait() const
Blocks until the operation completes.
Definition future.hpp:220
T wait_for(const std::chrono::duration< Rep, Period > &timeout) const
Blocks until the operation completes or the timeout expires.
Definition future.hpp:160
future()=default
Constructs an invalid (detached) future.
bool done() const noexcept
Non-blocking check for whether the operation has completed.
Definition future.hpp:208
IDFXX error handling.
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
@ timeout
Operation timed out.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120