24#include "lib/stdcompat/utility.h"
25#include "pw_assert/assert.h"
26#include "pw_async2/poll.h"
27#include "pw_async2/task.h"
28#include "pw_async2/waker.h"
29#include "pw_containers/intrusive_list.h"
30#include "pw_memory/container_of.h"
31#include "pw_sync/interrupt_spin_lock.h"
52 typename T::value_type;
55 static_cast<bool (T::*)() const
>(&T::is_pendable);
58 static_cast<bool (T::*)() const
>(&T::is_complete);
66 static_cast<Poll<typename T::value_type> (T::*)(Context&)
>(&T::Pend);
70} && std::default_initializable<T> && std::destructible<T> && std::movable<T>;
76template <
typename T,
typename =
void>
77struct is_future : std::false_type {};
82 std::void_t<typename T::value_type,
83 decltype(std::declval<T&>().Pend(std::declval<Context&>())),
84 decltype(std::declval<const T&>().is_pendable()),
85 decltype(std::declval<const T&>().is_complete())>>
87 std::is_convertible<decltype(&T::is_pendable), bool (T::*)() const>,
88 std::is_convertible<decltype(&T::is_complete), bool (T::*)() const>,
89 std::is_convertible<decltype(&T::Pend),
90 Poll<typename T::value_type> (T::*)(Context&)>,
91 std::is_default_constructible<T>,
92 std::is_destructible<T>> {};
99constexpr bool Future =
100 internal::is_future<std::remove_cv_t<std::remove_reference_t<T>>>::value;
108using FutureValue = std::conditional_t<std::is_void_v<typename T::value_type>,
110 typename T::value_type>;
134 : pend_state_(PendState::kPending), ready_(true) {}
142 : pend_state_(cpp20::exchange(other.pend_state_, PendState::kEmpty)),
143 ready_(cpp20::exchange(other.ready_, false)) {}
146 pend_state_ = cpp20::exchange(other.pend_state_, PendState::kEmpty);
147 ready_ = cpp20::exchange(other.ready_,
false);
153 return pend_state_ == PendState::kPending;
158 return pend_state_ == PendState::kComplete;
166 [[nodiscard]]
constexpr bool is_ready()
const {
return ready_; }
171 return pend_state_ != PendState::kEmpty;
191 enum class PendState :
unsigned char {
326 template <
typename FutureType>
330 auto poll = future.DoPend(cx);
331 if (poll.IsPending()) {
341 [[nodiscard]]
bool in_list()
const {
return !unlisted(); }
361 bool empty()
const {
return list_.empty(); }
369 FutureCore* PopIfAvailable() {
return list_.empty() ? nullptr : &Pop(); }
380 list_.front().WakeAndMarkReady();
384 void ResolveOneIfAvailable() {
385 if (!list_.empty()) {
407template <auto kGetFutureImpl, auto kGetFutureCore>
410 using value_type = std::remove_reference_t<
decltype(*kGetFutureImpl(
411 std::declval<FutureCore*>()))>;
412 using pointer = value_type*;
413 using reference = value_type&;
417 void Push(
FutureCore& future) { BaseFutureList::Push(future); }
418 void Push(reference future) { Push(kGetFutureCore(future)); }
421 BaseFutureList::PushRequireEmpty(future);
423 void PushRequireEmpty(reference future) {
424 PushRequireEmpty(kGetFutureCore(future));
428 return BaseFutureList::PushIfEmpty(future);
430 bool PushIfEmpty(reference future) {
431 return PushIfEmpty(kGetFutureCore(future));
434 pointer PopIfAvailable() {
435 return kGetFutureImpl(BaseFutureList::PopIfAvailable());
438 reference Pop() {
return *kGetFutureImpl(BaseFutureList::PopIfAvailable()); }
444 template <
typename Predicate>
446 auto previous = list().before_begin();
447 auto current = list().begin();
448 while (current != list().end()) {
449 pointer item = kGetFutureImpl(&(*current));
450 if (predicate(*item)) {
451 list().erase_after(previous);
460 template <
typename Resolver>
461 void ResolveAllWith(Resolver&& resolver) {
462 while (!list().empty()) {
467 template <
typename Resolver>
468 void ResolveOneWith(Resolver&& resolver) {
469 if (!list().empty()) {
479template <auto kMemberPtr>
Definition: intrusive_forward_list.h:99
void ResolveOne()
Definition: future.h:379
void ResolveAll()
Pops all futures and calls WakeAndMarkReady() on them.
pointer Remove(Predicate predicate)
Definition: future.h:445
void WakeAndMarkReady()
Definition: future.h:286
constexpr bool is_initialized() const
Definition: future.h:273
Waker & waker()
Definition: future.h:299
void Wake()
Definition: future.h:279
constexpr bool is_pendable() const
Definition: future.h:255
void MarkComplete()
Definition: future.h:306
constexpr FutureCore(FutureState::ReadyForCompletion)
Definition: future.h:246
constexpr bool is_complete() const
Definition: future.h:260
auto DoPend(FutureType &future, Context &cx)
Definition: future.h:327
void Unlist()
Removes this future from its list, if it is in one.
Definition: future.h:309
constexpr bool is_ready() const
Definition: future.h:270
void Reset()
Unlists the FutureCore and resets it to the empty state.
Definition: future.h:312
constexpr FutureCore(FutureState::Pending)
Definition: future.h:241
bool in_list() const
Definition: future.h:341
constexpr bool is_pendable() const
Definition: future.h:152
constexpr FutureState(ReadyForCompletion)
Definition: future.h:133
constexpr FutureState(FutureState &&other)
Definition: future.h:141
Pending
Tag for constructing an active future, for which Pend may be called.
Definition: future.h:117
constexpr FutureState()
Definition: future.h:125
void MarkComplete()
Definition: future.h:186
constexpr bool is_ready() const
Definition: future.h:166
constexpr FutureState(Pending)
Represents an active future, for which Pend may be called.
Definition: future.h:128
ReadyForCompletion
Definition: future.h:121
constexpr bool is_complete() const
Definition: future.h:157
void MarkReady()
Definition: future.h:180
constexpr bool is_initialized() const
Definition: future.h:170
std::conditional_t< std::is_void_v< typename T::value_type >, ReadyType, typename T::value_type > FutureValue
Definition: future.h:110
#define PW_ASYNC_STORE_WAKER(context, waker_out, wait_reason_string)
Definition: waker.h:64
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:296