24#include "lib/stdcompat/utility.h"
25#include "pw_assert/assert.h"
26#include "pw_async2/context.h"
27#include "pw_async2/poll.h"
28#include "pw_containers/intrusive_list.h"
29#include "pw_memory/container_of.h"
30#include "pw_sync/interrupt_spin_lock.h"
51 typename T::value_type;
54 static_cast<bool (T::*)() const
>(&T::is_pendable);
57 static_cast<bool (T::*)() const
>(&T::is_complete);
63 static_cast<Poll<typename T::value_type> (T::*)(Context&)
>(&T::Pend);
67} && std::default_initializable<T> && std::destructible<T> && std::movable<T>;
73template <
typename T,
typename =
void>
74struct is_future : std::false_type {};
79 std::void_t<typename T::value_type,
80 decltype(std::declval<T&>().Pend(std::declval<Context&>())),
81 decltype(std::declval<const T&>().is_pendable()),
82 decltype(std::declval<const T&>().is_complete())>>
84 std::is_convertible<decltype(&T::is_pendable), bool (T::*)() const>,
85 std::is_convertible<decltype(&T::is_complete), bool (T::*)() const>,
86 std::is_convertible<decltype(&T::Pend),
87 Poll<typename T::value_type> (T::*)(Context&)>,
88 std::is_default_constructible<T>,
89 std::is_destructible<T>> {};
96constexpr bool Future =
97 internal::is_future<std::remove_cv_t<std::remove_reference_t<T>>>::value;
105using FutureValue = std::conditional_t<std::is_void_v<typename T::value_type>,
107 typename T::value_type>;
138 : state_(cpp20::exchange(other.state_, State::kEmpty)) {}
141 state_ = cpp20::exchange(other.state_, State::kEmpty);
145 friend constexpr bool operator==(
const FutureState& lhs,
147 return lhs.state_ == rhs.state_;
150 friend constexpr bool operator!=(
const FutureState& lhs,
152 return lhs.state_ != rhs.state_;
157 return state_ > State::kComplete;
163 return state_ == State::kComplete;
170 return state_ == State::kReady;
176 return state_ != State::kEmpty;
179 void MarkReady() { state_ = State::kReady; }
181 void MarkComplete() { state_ = State::kComplete; }
184 enum class State :
unsigned char {
304 template <
typename FutureType>
308 auto poll = future.DoPend(cx);
309 if (poll.IsPending()) {
319 [[nodiscard]]
bool in_list()
const {
return !unlisted(); }
339 bool empty()
const {
return list_.empty(); }
347 FutureCore* PopIfAvailable() {
return list_.empty() ? nullptr : &Pop(); }
358 list_.front().WakeAndMarkReady();
362 void ResolveOneIfAvailable() {
363 if (!list_.empty()) {
385template <auto kGetFutureImpl, auto kGetFutureCore>
388 using value_type = std::remove_reference_t<
decltype(*kGetFutureImpl(
389 std::declval<FutureCore*>()))>;
390 using pointer = value_type*;
391 using reference = value_type&;
395 void Push(
FutureCore& future) { BaseFutureList::Push(future); }
396 void Push(reference future) { Push(kGetFutureCore(future)); }
399 BaseFutureList::PushRequireEmpty(future);
401 void PushRequireEmpty(reference future) {
402 PushRequireEmpty(kGetFutureCore(future));
406 return BaseFutureList::PushIfEmpty(future);
408 bool PushIfEmpty(reference future) {
409 return PushIfEmpty(kGetFutureCore(future));
412 pointer PopIfAvailable() {
413 return kGetFutureImpl(BaseFutureList::PopIfAvailable());
416 reference Pop() {
return *kGetFutureImpl(BaseFutureList::PopIfAvailable()); }
418 template <
typename Resolver>
419 void ResolveAllWith(Resolver&& resolver) {
420 while (!list().empty()) {
425 template <
typename Resolver>
426 void ResolveOneWith(Resolver&& resolver) {
427 if (!list().empty()) {
437template <auto kMemberPtr>
Definition: intrusive_forward_list.h:99
void ResolveOne()
Definition: future.h:357
void ResolveAll()
Pops all futures and calls WakeAndMarkReady() on them.
void WakeAndMarkReady()
Definition: future.h:267
constexpr bool is_initialized() const
Definition: future.h:257
Waker & waker()
Definition: future.h:277
void Wake()
Definition: future.h:263
constexpr bool is_pendable() const
Definition: future.h:239
void MarkComplete()
Definition: future.h:284
constexpr FutureCore(FutureState::ReadyForCompletion)
Definition: future.h:230
constexpr bool is_complete() const
Definition: future.h:244
auto DoPend(FutureType &future, Context &cx)
Definition: future.h:305
void Unlist()
Removes this future from its list, if it is in one.
Definition: future.h:287
constexpr bool is_ready() const
Definition: future.h:254
void Reset()
Unlists the FutureCore and resets it to the empty state.
Definition: future.h:290
constexpr FutureCore(FutureState::Pending)
Definition: future.h:225
bool in_list() const
Definition: future.h:319
constexpr bool is_pendable() const
Definition: future.h:156
constexpr FutureState(ReadyForCompletion)
Definition: future.h:130
constexpr FutureState(FutureState &&other)
Definition: future.h:137
Pending
Tag for constructing an active future, for which Pend may be called.
Definition: future.h:114
constexpr FutureState()
Definition: future.h:122
constexpr bool is_ready() const
Definition: future.h:169
constexpr FutureState(Pending)
Represents an active future, for which Pend may be called.
Definition: future.h:125
ReadyForCompletion
Definition: future.h:118
constexpr bool is_complete() const
Definition: future.h:162
constexpr bool is_initialized() const
Definition: future.h:175
std::conditional_t< std::is_void_v< typename T::value_type >, ReadyType, typename T::value_type > FutureValue
Definition: future.h:107
#define PW_ASYNC_STORE_WAKER(context, waker_or_queue_out, wait_reason_string)
Definition: waker.h:58
void PushBackSlow(IntrusiveForwardList< T > &forward_list, T &item)
Inserts an element at the end of the forward list. Runs in O(n) time.
Definition: intrusive_forward_list.h:50
#define PW_NO_LOCK_SAFETY_ANALYSIS
Definition: lock_annotations.h:292