20#include "pw_assert/assert.h"
21#include "pw_async2/context.h"
22#include "pw_async2/poll.h"
23#include "pw_containers/intrusive_list.h"
24#include "pw_sync/interrupt_spin_lock.h"
61template <
typename Derived,
typename T>
64 using value_type = std::conditional_t<std::is_void_v<T>,
ReadyType, T>;
77 derived().DoMarkComplete();
88 constexpr Future() =
default;
91 Derived& derived() {
return static_cast<Derived&
>(*this); }
92 const Derived& derived()
const {
return static_cast<const Derived&
>(*this); }
97template <
typename D,
typename V>
98std::true_type IsFuture(
const volatile Future<D, V>*);
100std::false_type IsFuture(...);
105struct is_future : decltype(internal::IsFuture(std::declval<T*>())){};
108constexpr bool is_future_v =
134template <
typename FutureType,
typename Lock = sync::InterruptSpinLock>
143 void Push(FutureType& future) {
144 std::lock_guard
lock(lock_);
149 std::optional<std::reference_wrapper<FutureType>>
Pop() {
150 std::lock_guard
lock(lock_);
151 if (futures_.
empty()) {
154 FutureType& future = futures_.
front();
156 return std::ref(future);
161 std::lock_guard
lock(lock_);
162 return futures_.
empty();
171 template <
typename,
typename>
174 using LockType = Lock;
191template <
typename FutureType>
200 void Set(FutureType& future) {
215 [[nodiscard]] std::optional<std::reference_wrapper<FutureType>>
Take() {
223 template <
typename,
typename>
280template <
typename Derived,
typename T>
282 :
public Future<ListableFutureWithWaker<Derived, T>, T>,
294 if (provider_ !=
nullptr) {
295 provider_->lock().lock();
300 if (provider_ !=
nullptr) {
301 provider_->lock().unlock();
306 provider_ = provider;
312 PW_ASSERT(provider_ !=
nullptr);
316 PW_ASSERT(provider_ !=
nullptr);
320 explicit operator bool()
const {
return provider_ !=
nullptr; }
326 : provider_(provider) {}
349 : provider_(nullptr), complete_(state == kMovedFrom) {}
352 : provider_(&provider) {
353 provider.
Push(derived());
355 explicit ListableFutureWithWaker(SingleFutureProvider<Derived>& single)
356 : ListableFutureWithWaker(single.inner_) {}
358 ~ListableFutureWithWaker() {
362 std::lock_guard guard(lock());
363 if (!this->unlisted()) {
368 void MoveFrom(ListableFutureWithWaker& other) {
369 complete_ = std::exchange(other.complete_,
true);
370 provider_ = std::exchange(other.provider_,
nullptr);
371 waker_ = std::move(other.waker_);
374 std::lock_guard guard(lock());
375 if (!other.unlisted()) {
376 this->replace(other);
381 ListFutureProvider<Derived>& provider() {
return *provider_; }
383 Lock& lock() {
return provider_; }
386 void Wake() { std::move(waker_).Wake(); }
396 std::is_same_v<std::remove_extent_t<
decltype(Derived::kWaitReason)>,
398 "kWaitReason must be a character array");
410 std::lock_guard guard(lock());
411 if (provider_ && this->unlisted()) {
412 provider_->futures_.
push_back(derived());
416 void DoMarkComplete() { complete_ =
true; }
417 bool DoIsComplete()
const {
return complete_; }
419 Derived& derived() {
return static_cast<Derived&
>(*this); }
423 bool complete_ =
false;
Poll< value_type > Pend(Context &cx)
Definition: future.h:73
bool is_complete() const
Definition: future.h:85
bool empty()
Returns true if there are no futures listed.
Definition: future.h:160
Lock & lock()
Provides access to the list's internal lock.
Definition: future.h:166
void Push(FutureType &future)
Adds a future to the end of the list.
Definition: future.h:143
std::optional< std::reference_wrapper< FutureType > > Pop()
Removes and returns the first future from the list, if one exists.
Definition: future.h:149
void Wake()
Wakes the task waiting on the future.
Definition: future.h:386
ListableFutureWithWaker(ConstructedState state)
Definition: future.h:348
ConstructedState
Tag to prevent accidental default construction.
Definition: future.h:334
bool has_future()
Returns true if the provider has a future.
Definition: future.h:220
bool TrySet(FutureType &future)
Attempts to set the provider's future, returning true if successful.
Definition: future.h:206
std::optional< std::reference_wrapper< FutureType > > Take()
Claims the provider's future, leaving it unset.
Definition: future.h:215
void Set(FutureType &future)
Sets the provider's future. Crashes if a future is already set.
Definition: future.h:200
Definition: intrusive_list.h:88
constexpr bool IsReady() const noexcept
Returns whether or not this value is Ready.
Definition: poll.h:133
constexpr bool IsPending() const noexcept
Returns whether or not this value is Pending.
Definition: poll.h:136
#define PW_ASYNC_STORE_WAKER(context, waker_or_queue_out, wait_reason_string)
Definition: waker.h:60
void push_back(T &item)
Inserts an element at the end of the list.
Definition: intrusive_list.h:255
bool empty() const noexcept
Definition: intrusive_list.h:207
void pop_front()
Removes the first item in the list. The list must not be empty.
Definition: intrusive_list.h:264
T & front()
Reference to the first element in the list. Undefined behavior if empty().
Definition: intrusive_list.h:167
#define PW_LOCKABLE(name)
Definition: lock_annotations.h:208
#define PW_EXCLUSIVE_LOCK_FUNCTION(...)
Definition: lock_annotations.h:230
#define PW_UNLOCK_FUNCTION(...)
Definition: lock_annotations.h:247