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>;
131 : pend_state_(PendState::kPending), ready_(true) {}
139 : pend_state_(cpp20::exchange(other.pend_state_, PendState::kEmpty)),
140 ready_(cpp20::exchange(other.ready_, false)) {}
143 pend_state_ = cpp20::exchange(other.pend_state_, PendState::kEmpty);
144 ready_ = cpp20::exchange(other.ready_,
false);
150 return pend_state_ == PendState::kPending;
155 return pend_state_ == PendState::kComplete;
163 [[nodiscard]]
constexpr bool is_ready()
const {
return ready_; }
168 return pend_state_ != PendState::kEmpty;
188 enum class PendState :
unsigned char {
317 template <
typename FutureType>
321 auto poll = future.DoPend(cx);
322 if (poll.IsPending()) {
332 [[nodiscard]]
bool in_list()
const {
return !unlisted(); }
352 bool empty()
const {
return list_.empty(); }
360 FutureCore* PopIfAvailable() {
return list_.empty() ? nullptr : &Pop(); }
371 list_.front().WakeAndMarkReady();
375 void ResolveOneIfAvailable() {
376 if (!list_.empty()) {
398template <auto kGetFutureImpl, auto kGetFutureCore>
401 using value_type = std::remove_reference_t<
decltype(*kGetFutureImpl(
402 std::declval<FutureCore*>()))>;
403 using pointer = value_type*;
404 using reference = value_type&;
408 void Push(
FutureCore& future) { BaseFutureList::Push(future); }
409 void Push(reference future) { Push(kGetFutureCore(future)); }
412 BaseFutureList::PushRequireEmpty(future);
414 void PushRequireEmpty(reference future) {
415 PushRequireEmpty(kGetFutureCore(future));
419 return BaseFutureList::PushIfEmpty(future);
421 bool PushIfEmpty(reference future) {
422 return PushIfEmpty(kGetFutureCore(future));
425 pointer PopIfAvailable() {
426 return kGetFutureImpl(BaseFutureList::PopIfAvailable());
429 reference Pop() {
return *kGetFutureImpl(BaseFutureList::PopIfAvailable()); }
435 template <
typename Predicate>
437 auto previous = list().before_begin();
438 auto current = list().begin();
439 while (current != list().end()) {
440 pointer item = kGetFutureImpl(&(*current));
441 if (predicate(*item)) {
442 list().erase_after(previous);
451 template <
typename Resolver>
452 void ResolveAllWith(Resolver&& resolver) {
453 while (!list().empty()) {
458 template <
typename Resolver>
459 void ResolveOneWith(Resolver&& resolver) {
460 if (!list().empty()) {
470template <auto kMemberPtr>
Definition: intrusive_forward_list.h:99
void ResolveOne()
Definition: future.h:370
void ResolveAll()
Pops all futures and calls WakeAndMarkReady() on them.
pointer Remove(Predicate predicate)
Definition: future.h:436
void WakeAndMarkReady()
Definition: future.h:277
constexpr bool is_initialized() const
Definition: future.h:264
Waker & waker()
Definition: future.h:290
void Wake()
Definition: future.h:270
constexpr bool is_pendable() const
Definition: future.h:246
void MarkComplete()
Definition: future.h:297
constexpr FutureCore(FutureState::ReadyForCompletion)
Definition: future.h:237
constexpr bool is_complete() const
Definition: future.h:251
auto DoPend(FutureType &future, Context &cx)
Definition: future.h:318
void Unlist()
Removes this future from its list, if it is in one.
Definition: future.h:300
constexpr bool is_ready() const
Definition: future.h:261
void Reset()
Unlists the FutureCore and resets it to the empty state.
Definition: future.h:303
constexpr FutureCore(FutureState::Pending)
Definition: future.h:232
bool in_list() const
Definition: future.h:332
constexpr bool is_pendable() const
Definition: future.h:149
constexpr FutureState(ReadyForCompletion)
Definition: future.h:130
constexpr FutureState(FutureState &&other)
Definition: future.h:138
Pending
Tag for constructing an active future, for which Pend may be called.
Definition: future.h:114
constexpr FutureState()
Definition: future.h:122
void MarkComplete()
Definition: future.h:183
constexpr bool is_ready() const
Definition: future.h:163
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:154
void MarkReady()
Definition: future.h:177
constexpr bool is_initialized() const
Definition: future.h:167
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