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"
31template <std::constructible_from<pw::Status> T>
52void LogCoroAllocationFailure(
size_t requested_size);
63 value_ = std::forward<U>(value);
71 PW_ASSERT(value_.has_value());
76 std::optional<T> value_;
88using OptionalOrDefault =
89 std::conditional<std::is_default_constructible<T>::value,
98template <
typename PromiseType>
106 : promise_handle_(std::move(promise_handle)) {}
111 : promise_handle_(std::move(other.promise_handle_)) {
112 other.promise_handle_ =
nullptr;
117 OwningCoroutineHandle& operator=(OwningCoroutineHandle&& other) {
119 promise_handle_ = std::move(other.promise_handle_);
120 other.promise_handle_ =
nullptr;
125 ~OwningCoroutineHandle() { Release(); }
131 [[nodiscard]]
bool IsValid()
const {
132 return promise_handle_.address() !=
nullptr;
138 [[nodiscard]] PromiseType& promise()
const {
139 return promise_handle_.promise();
145 [[nodiscard]]
bool done()
const {
return promise_handle_.done(); }
151 void resume() { promise_handle_.resume(); }
157 void* address = promise_handle_.address();
158 if (address !=
nullptr) {
159 pw::allocator::Deallocator& dealloc = promise_handle_.promise().dealloc_;
160 promise_handle_.destroy();
161 promise_handle_ =
nullptr;
162 dealloc.Deallocate(address);
168 std::coroutine_handle<PromiseType> promise_handle_;
172template <
typename Pendable,
typename PromiseType>
187 OptionalOrDefault<T>* output;
200using PendFillReturnValueFn =
215 template <
typename... Args>
217 : dealloc_(cx.alloc()), currently_pending_(
nullptr), in_out_(
nullptr) {}
220 template <
typename MethodReceiver,
typename... Args>
222 : dealloc_(cx.alloc()), currently_pending_(
nullptr), in_out_(
nullptr) {}
230 std::suspend_always initial_suspend() {
return {}; }
239 std::suspend_always final_suspend()
noexcept {
return {}; }
243 template <std::convertible_to<T> From>
244 void return_value(From&& value) {
245 *in_out_->output = std::forward<From>(value);
252 void unhandled_exception() { PW_ASSERT(
false); }
255 static Coro<T> get_return_object_on_allocation_failure();
261 template <
typename... Args>
262 static void*
operator new(std::size_t size,
264 const Args&...)
noexcept {
265 return SharedNew(coro_cx, size,
alignof(std::max_align_t));
272 template <
typename... Args>
273 static void*
operator new(std::size_t size,
274 std::align_val_t align,
276 const Args&...)
noexcept {
277 return SharedNew(coro_cx, size,
static_cast<size_t>(align));
283 template <
typename MethodReceiver,
typename... Args>
284 static void*
operator new(std::size_t size,
285 const MethodReceiver&,
287 const Args&...)
noexcept {
288 return SharedNew(coro_cx, size,
alignof(std::max_align_t));
294 template <
typename MethodReceiver,
typename... Args>
295 static void*
operator new(std::size_t size,
296 std::align_val_t align,
297 const MethodReceiver&,
299 const Args&...)
noexcept {
300 return SharedNew(coro_cx, size,
static_cast<size_t>(align));
305 std::size_t align)
noexcept {
307 if (ptr ==
nullptr) {
308 internal::LogCoroAllocationFailure(size);
321 static void operator delete(
void*) {}
326 template <
typename Pendable>
327 requires(!std::is_reference_v<Pendable>)
332 template <
typename Pendable>
338 Context& cx() {
return *in_out_->input_cx; }
340 pw::allocator::Deallocator& dealloc_;
341 PendFillReturnValueFn currently_pending_;
349template <
typename Pendable,
typename PromiseType>
353 using OutputType = std::remove_cvref_t<
354 decltype(std::declval<std::remove_pointer_t<Pendable>>()
355 .Pend(std::declval<Context&>())
358 Awaitable(Pendable&& pendable) : state_(std::forward<Pendable>(pendable)) {}
361 bool await_ready() {
return false; }
371 Context& cx = promise.promise().cx();
372 if (PendFillReturnValue(cx).IsPending()) {
374 promise.promise().currently_pending_ = [
this](
Context& lambda_cx) {
375 return PendFillReturnValue(lambda_cx);
386 OutputType&& await_resume() {
387 return std::move(std::get<OutputType>(state_));
390 auto& PendableNoPtr() {
391 if constexpr (std::is_pointer_v<Pendable>) {
392 return *std::get<Pendable>(state_);
394 return std::get<Pendable>(state_);
404 Poll<> PendFillReturnValue(Context& cx) {
405 Poll<OutputType> poll_res(PendableNoPtr().Pend(cx));
406 if (poll_res.IsPending()) {
409 state_ = std::move(*poll_res);
414 std::variant<Pendable, OutputType> state_;
462template <std::constructible_from<pw::Status> T>
474 [[nodiscard]]
bool IsValid()
const {
return promise_handle_.IsValid(); }
484 return Ready(Status::Internal());
490 if (promise_handle_.promise().currently_pending_ !=
nullptr &&
491 promise_handle_.promise().currently_pending_(cx).IsPending()) {
497 internal::OptionalOrDefault<T> return_value;
498 in_out.input_cx = &cx;
499 in_out.output = &return_value;
500 promise_handle_.promise().in_out_ = &in_out;
504 promise_handle_.resume();
505 if (!promise_handle_.done()) {
511 promise_handle_.Release();
531 : promise_handle_(std::move(promise_handle)) {}
541Coro<T> CoroPromiseType<T>::get_return_object() {
542 return internal::OwningCoroutineHandle<CoroPromiseType<T>>(
543 std::coroutine_handle<CoroPromiseType<T>>::from_promise(*
this));
547Coro<T> CoroPromiseType<T>::get_return_object_on_allocation_failure() {
548 return internal::OwningCoroutineHandle<CoroPromiseType<T>>(
nullptr);
Definition: allocator.h:34
Definition: dispatcher_base.h:52
Context required for creating and executing coroutines.
Definition: coro.h:35
CoroContext(pw::allocator::Allocator &alloc)
Definition: coro.h:39
static Coro Empty()
Creates an empty, invalid coroutine object.
Definition: coro.h:466
::pw::async2::internal::CoroPromiseType< T > promise_type
Definition: coro.h:521
bool IsValid() const
Definition: coro.h:474
Poll< T > Pend(Context &cx)
Definition: coro.h:480
bool await_suspend(const std::coroutine_handle< PromiseType > &promise)
Definition: coro.h:370
OwningCoroutineHandle(std::coroutine_handle< PromiseType > &&promise_handle)
Take ownership of promise_handle.
Definition: coro.h:105
fit::inline_function< FunctionType, inline_target_size > InlineFunction
Definition: function.h:91