20#include "pw_allocator/allocator.h"
21#include "pw_allocator/layout.h"
22#include "pw_async2/dispatcher.h"
23#include "pw_function/function.h"
24#include "pw_log/log.h"
25#include "pw_status/status.h"
26#include "pw_status/try.h"
33template <std::constructible_from<pw::Status> T>
56void LogCoroAllocationFailure(
size_t requested_size);
67 value_ = std::forward<U>(value);
75 PW_ASSERT(value_.has_value());
80 std::optional<T> value_;
92using OptionalOrDefault =
93 std::conditional<std::is_default_constructible<T>::value,
102template <
typename PromiseType>
110 : promise_handle_(std::move(promise_handle)) {}
115 : promise_handle_(std::move(other.promise_handle_)) {
116 other.promise_handle_ =
nullptr;
121 OwningCoroutineHandle& operator=(OwningCoroutineHandle&& other) {
123 promise_handle_ = std::move(other.promise_handle_);
124 other.promise_handle_ =
nullptr;
129 ~OwningCoroutineHandle() { Release(); }
135 [[nodiscard]]
bool IsValid()
const {
136 return promise_handle_.address() !=
nullptr;
142 [[nodiscard]] PromiseType& promise()
const {
143 return promise_handle_.promise();
149 [[nodiscard]]
bool done()
const {
return promise_handle_.done(); }
155 void resume() { promise_handle_.resume(); }
161 void* address = promise_handle_.address();
162 if (address !=
nullptr) {
163 pw::allocator::Deallocator& dealloc = promise_handle_.promise().dealloc_;
164 promise_handle_.destroy();
165 promise_handle_ =
nullptr;
166 dealloc.Deallocate(address);
172 std::coroutine_handle<PromiseType> promise_handle_;
176template <
typename Pendable,
typename PromiseType>
191 OptionalOrDefault<T>* output;
204using PendFillReturnValueFn =
219 template <
typename... Args>
221 : dealloc_(cx.alloc()), currently_pending_(
nullptr), in_out_(
nullptr) {}
224 template <
typename MethodReceiver,
typename... Args>
226 : dealloc_(cx.alloc()), currently_pending_(
nullptr), in_out_(
nullptr) {}
234 std::suspend_always initial_suspend() {
return {}; }
243 std::suspend_always final_suspend()
noexcept {
return {}; }
247 template <std::convertible_to<T> From>
248 void return_value(From&& value) {
249 *in_out_->output = std::forward<From>(value);
256 void unhandled_exception() { PW_ASSERT(
false); }
259 static Coro<T> get_return_object_on_allocation_failure();
265 template <
typename... Args>
266 static void*
operator new(std::size_t size,
268 const Args&...)
noexcept {
269 return SharedNew(coro_cx, size,
alignof(std::max_align_t));
276 template <
typename... Args>
277 static void*
operator new(std::size_t size,
278 std::align_val_t align,
280 const Args&...)
noexcept {
281 return SharedNew(coro_cx, size,
static_cast<size_t>(align));
287 template <
typename MethodReceiver,
typename... Args>
288 static void*
operator new(std::size_t size,
289 const MethodReceiver&,
291 const Args&...)
noexcept {
292 return SharedNew(coro_cx, size,
alignof(std::max_align_t));
298 template <
typename MethodReceiver,
typename... Args>
299 static void*
operator new(std::size_t size,
300 std::align_val_t align,
301 const MethodReceiver&,
303 const Args&...)
noexcept {
304 return SharedNew(coro_cx, size,
static_cast<size_t>(align));
309 std::size_t align)
noexcept {
311 if (ptr ==
nullptr) {
312 internal::LogCoroAllocationFailure(size);
325 static void operator delete(
void*) {}
330 template <
typename Pendable>
331 requires(!std::is_reference_v<Pendable>)
336 template <
typename Pendable>
342 Context& cx() {
return *in_out_->input_cx; }
344 pw::allocator::Deallocator& dealloc_;
345 PendFillReturnValueFn currently_pending_;
353template <
typename Pendable,
typename PromiseType>
357 using value_type = std::remove_cvref_t<
358 decltype(std::declval<std::remove_pointer_t<Pendable>>()
359 .Pend(std::declval<Context&>())
362 Awaitable(Pendable&& pendable) : state_(std::forward<Pendable>(pendable)) {}
365 bool await_ready() {
return false; }
375 Context& cx = promise.promise().cx();
376 if (PendFillReturnValue(cx).IsPending()) {
378 promise.promise().currently_pending_ = [
this](
Context& lambda_cx) {
379 return PendFillReturnValue(lambda_cx);
390 value_type&& await_resume() {
391 return std::move(std::get<value_type>(state_));
394 auto& PendableNoPtr() {
395 if constexpr (std::is_pointer_v<Pendable>) {
396 return *std::get<Pendable>(state_);
398 return std::get<Pendable>(state_);
408 Poll<> PendFillReturnValue(Context& cx) {
409 Poll<value_type> poll_res(PendableNoPtr().Pend(cx));
410 if (poll_res.IsPending()) {
413 state_ = std::move(*poll_res);
418 std::variant<Pendable, value_type> state_;
468template <std::constructible_from<pw::Status> T>
480 [[nodiscard]]
bool IsValid()
const {
return promise_handle_.IsValid(); }
496 if (promise_handle_.promise().currently_pending_ !=
nullptr &&
497 promise_handle_.promise().currently_pending_(cx).IsPending()) {
503 internal::OptionalOrDefault<T> return_value;
504 in_out.input_cx = &cx;
505 in_out.output = &return_value;
506 promise_handle_.promise().in_out_ = &in_out;
510 promise_handle_.resume();
511 if (!promise_handle_.done()) {
517 promise_handle_.Release();
537 : promise_handle_(std::move(promise_handle)) {}
549Coro<T> CoroPromiseType<T>::get_return_object() {
550 return internal::OwningCoroutineHandle<CoroPromiseType<T>>(
551 std::coroutine_handle<CoroPromiseType<T>>::from_promise(*
this));
555Coro<T> CoroPromiseType<T>::get_return_object_on_allocation_failure() {
556 return internal::OwningCoroutineHandle<CoroPromiseType<T>>(
nullptr);
Definition: allocator.h:36
static constexpr Status Internal()
Internal error occurred; e.g. system invariants were violated.
Definition: status.h:182
Context required for creating and executing coroutines.
Definition: coro.h:37
CoroContext(pw::allocator::Allocator &alloc)
Definition: coro.h:41
static Coro Empty()
Creates an empty, invalid coroutine object.
Definition: coro.h:472
::pw::async2::internal::CoroPromiseType< T > promise_type
Definition: coro.h:527
bool IsValid() const
Definition: coro.h:480
Poll< T > Pend(Context &cx)
Definition: coro.h:486
bool await_suspend(const std::coroutine_handle< PromiseType > &promise)
Definition: coro.h:374
OwningCoroutineHandle(std::coroutine_handle< PromiseType > &&promise_handle)
Take ownership of promise_handle.
Definition: coro.h:109
constexpr PendingType Pending()
Returns a value indicating that an operation was not yet able to complete.
Definition: poll.h:271
constexpr Poll Ready()
Returns a value indicating completion.
Definition: poll.h:255
fit::inline_function< FunctionType, inline_target_size > InlineFunction
Definition: function.h:90