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);
65 static_cast<Poll<typename T::value_type> (T::*)(Context&)
>(&T::Pend);
69} && std::default_initializable<T> && std::destructible<T> && std::movable<T>;
75template <
typename T,
typename =
void>
76struct is_future : std::false_type {};
81 std::void_t<typename T::value_type,
82 decltype(std::declval<T&>().Pend(std::declval<Context&>())),
83 decltype(std::declval<const T&>().is_pendable()),
84 decltype(std::declval<const T&>().is_complete())>>
86 std::is_convertible<decltype(&T::is_pendable), bool (T::*)() const>,
87 std::is_convertible<decltype(&T::is_complete), bool (T::*)() const>,
88 std::is_convertible<decltype(&T::Pend),
89 Poll<typename T::value_type> (T::*)(Context&)>,
90 std::is_default_constructible<T>,
91 std::is_destructible<T>> {};
98constexpr bool Future =
99 internal::is_future<std::remove_cv_t<std::remove_reference_t<T>>>::value;
107using FutureValue = std::conditional_t<std::is_void_v<typename T::value_type>,
109 typename T::value_type>;
133 : pend_state_(PendState::kPending), ready_(true) {}
141 : pend_state_(cpp20::exchange(other.pend_state_, PendState::kEmpty)),
142 ready_(cpp20::exchange(other.ready_, false)) {}
145 pend_state_ = cpp20::exchange(other.pend_state_, PendState::kEmpty);
146 ready_ = cpp20::exchange(other.ready_,
false);
152 return pend_state_ == PendState::kPending;
157 return pend_state_ == PendState::kComplete;
165 [[nodiscard]]
constexpr bool is_ready()
const {
return ready_; }
170 return pend_state_ != PendState::kEmpty;
190 enum class PendState :
unsigned char {
319 template <
typename FutureType>
323 auto poll = future.DoPend(cx);
324 if (poll.IsPending()) {
334 [[nodiscard]]
bool in_list()
const {
return !unlisted(); }
354 bool empty()
const {
return list_.empty(); }
362 FutureCore* PopIfAvailable() {
return list_.empty() ? nullptr : &Pop(); }
373 list_.front().WakeAndMarkReady();
377 void ResolveOneIfAvailable() {
378 if (!list_.empty()) {
400template <auto kGetFutureImpl, auto kGetFutureCore>
403 using value_type = std::remove_reference_t<
decltype(*kGetFutureImpl(
404 std::declval<FutureCore*>()))>;
405 using pointer = value_type*;
406 using reference = value_type&;
410 void Push(
FutureCore& future) { BaseFutureList::Push(future); }
411 void Push(reference future) { Push(kGetFutureCore(future)); }
414 BaseFutureList::PushRequireEmpty(future);
416 void PushRequireEmpty(reference future) {
417 PushRequireEmpty(kGetFutureCore(future));
421 return BaseFutureList::PushIfEmpty(future);
423 bool PushIfEmpty(reference future) {
424 return PushIfEmpty(kGetFutureCore(future));
427 pointer PopIfAvailable() {
428 return kGetFutureImpl(BaseFutureList::PopIfAvailable());
431 reference Pop() {
return *kGetFutureImpl(BaseFutureList::PopIfAvailable()); }
437 template <
typename Predicate>
439 auto previous = list().before_begin();
440 auto current = list().begin();
441 while (current != list().end()) {
442 pointer item = kGetFutureImpl(&(*current));
443 if (predicate(*item)) {
444 list().erase_after(previous);
453 template <
typename Resolver>
454 void ResolveAllWith(Resolver&& resolver) {
455 while (!list().empty()) {
460 template <
typename Resolver>
461 void ResolveOneWith(Resolver&& resolver) {
462 if (!list().empty()) {
472template <auto kMemberPtr>
Definition: intrusive_forward_list.h:99
void ResolveOne()
Definition: future.h:372
void ResolveAll()
Pops all futures and calls WakeAndMarkReady() on them.
pointer Remove(Predicate predicate)
Definition: future.h:438
void WakeAndMarkReady()
Definition: future.h:279
constexpr bool is_initialized() const
Definition: future.h:266
Waker & waker()
Definition: future.h:292
void Wake()
Definition: future.h:272
constexpr bool is_pendable() const
Definition: future.h:248
void MarkComplete()
Definition: future.h:299
constexpr FutureCore(FutureState::ReadyForCompletion)
Definition: future.h:239
constexpr bool is_complete() const
Definition: future.h:253
auto DoPend(FutureType &future, Context &cx)
Definition: future.h:320
void Unlist()
Removes this future from its list, if it is in one.
Definition: future.h:302
constexpr bool is_ready() const
Definition: future.h:263
void Reset()
Unlists the FutureCore and resets it to the empty state.
Definition: future.h:305
constexpr FutureCore(FutureState::Pending)
Definition: future.h:234
bool in_list() const
Definition: future.h:334
constexpr bool is_pendable() const
Definition: future.h:151
constexpr FutureState(ReadyForCompletion)
Definition: future.h:132
constexpr FutureState(FutureState &&other)
Definition: future.h:140
Pending
Tag for constructing an active future, for which Pend may be called.
Definition: future.h:116
constexpr FutureState()
Definition: future.h:124
void MarkComplete()
Definition: future.h:185
constexpr bool is_ready() const
Definition: future.h:165
constexpr FutureState(Pending)
Represents an active future, for which Pend may be called.
Definition: future.h:127
ReadyForCompletion
Definition: future.h:120
constexpr bool is_complete() const
Definition: future.h:156
void MarkReady()
Definition: future.h:179
constexpr bool is_initialized() const
Definition: future.h:169
std::conditional_t< std::is_void_v< typename T::value_type >, ReadyType, typename T::value_type > FutureValue
Definition: future.h:109
#define PW_ASYNC_STORE_WAKER(context, waker_or_queue_out, wait_reason_string)
Definition: waker.h:60
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