arm: async changes
- more tracing - pending resume() notifications - idle function returns bool (useful for testing) may not build (more stuff coming in later commits)
This commit is contained in:
125
arm/async.h
125
arm/async.h
@@ -1,18 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <coroutine>
|
||||
#include <utility>
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#include <experimental/coroutine>
|
||||
namespace std {
|
||||
using namespace experimental;
|
||||
}
|
||||
#else // __clang__
|
||||
#include <coroutine>
|
||||
#endif // __clang__
|
||||
|
||||
namespace async {
|
||||
|
||||
struct task_final_suspend {
|
||||
bool await_ready() noexcept(true) { return false; }
|
||||
void await_suspend(std::coroutine_handle<> h) noexcept(true) {
|
||||
if (parent) {
|
||||
TRACE(tracing::TraceEvent::kAsyncCallParent);
|
||||
parent();
|
||||
TRACE(tracing::TraceEvent::kAsyncCallParentDone);
|
||||
}
|
||||
h.destroy();
|
||||
}
|
||||
void await_resume() noexcept(true) {}
|
||||
|
||||
@@ -20,35 +31,7 @@ struct task_final_suspend {
|
||||
};
|
||||
|
||||
template <typename T = void>
|
||||
struct task {
|
||||
struct promise_type;
|
||||
using handle_type = std::coroutine_handle<promise_type>;
|
||||
|
||||
struct promise_type {
|
||||
task get_return_object() {
|
||||
return {.h = handle_type::from_promise(*this)};
|
||||
}
|
||||
std::suspend_always initial_suspend() noexcept { return {}; }
|
||||
task_final_suspend final_suspend() noexcept {
|
||||
return {.parent = parent};
|
||||
}
|
||||
void return_value(T&& value) { ret_value = std::move(value); }
|
||||
void unhandled_exception() {}
|
||||
|
||||
T ret_value;
|
||||
std::coroutine_handle<> parent;
|
||||
};
|
||||
|
||||
// awaitable
|
||||
bool await_ready() { return h.done(); }
|
||||
void await_suspend(std::coroutine_handle<> ha) {
|
||||
h();
|
||||
h.promise().parent = ha;
|
||||
}
|
||||
T await_resume() { return std::move(h.promise().ret_value); }
|
||||
|
||||
std::coroutine_handle<promise_type> h;
|
||||
};
|
||||
struct task;
|
||||
|
||||
template <>
|
||||
struct task<void> {
|
||||
@@ -64,22 +47,94 @@ struct task<void> {
|
||||
return {.parent = parent};
|
||||
}
|
||||
void return_void() {}
|
||||
void unhandled_exception() {}
|
||||
void unhandled_exception() {
|
||||
TRACE(tracing::TraceEvent::kAsyncException);
|
||||
}
|
||||
|
||||
std::coroutine_handle<> parent;
|
||||
};
|
||||
|
||||
// awaitable
|
||||
bool await_ready() { return h.done(); }
|
||||
void await_suspend(std::coroutine_handle<> ha) {
|
||||
h.promise().parent = ha;
|
||||
bool await_ready() {
|
||||
TRACE(tracing::TraceEvent::kAsyncCoAwait);
|
||||
h();
|
||||
if (h.done()) {
|
||||
TRACE(tracing::TraceEvent::kAsyncDestroy); h.destroy();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void await_suspend(std::coroutine_handle<> ha) {
|
||||
TRACE(tracing::TraceEvent::kAsyncSuspend);
|
||||
h.promise().parent = ha;
|
||||
}
|
||||
void await_resume() {}
|
||||
|
||||
std::coroutine_handle<promise_type> h;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct task {
|
||||
struct promise_type;
|
||||
using handle_type = std::coroutine_handle<promise_type>;
|
||||
|
||||
struct promise_type {
|
||||
task get_return_object() {
|
||||
return {.h = handle_type::from_promise(*this)};
|
||||
}
|
||||
std::suspend_always initial_suspend() noexcept { return {}; }
|
||||
task_final_suspend final_suspend() noexcept {
|
||||
return {.parent = parent};
|
||||
}
|
||||
void return_value(T&& value) { ret_value = std::move(value); }
|
||||
void unhandled_exception() {
|
||||
TRACE(tracing::TraceEvent::kAsyncException);
|
||||
}
|
||||
template<std::convertible_to<T> From>
|
||||
task_final_suspend yield_value(From&& value) {
|
||||
ret_value = std::forward<From>(value);
|
||||
result_ready = true;
|
||||
return {.parent = parent};
|
||||
}
|
||||
|
||||
T ret_value;
|
||||
bool result_ready = false;
|
||||
std::coroutine_handle<> parent;
|
||||
};
|
||||
|
||||
// awaitable
|
||||
bool await_ready() {
|
||||
h.promise().parent = {};
|
||||
TRACE(tracing::TraceEvent::kAsyncCoAwait);
|
||||
h();
|
||||
if (h.promise().result_ready) {
|
||||
return true;
|
||||
}
|
||||
if (h.done()) {
|
||||
destroyed = true;
|
||||
ret_value = std::move(h.promise().ret_value);
|
||||
TRACE(tracing::TraceEvent::kAsyncDestroy); h.destroy();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void await_suspend(std::coroutine_handle<> ha) {
|
||||
TRACE(tracing::TraceEvent::kAsyncSuspend);
|
||||
h.promise().parent = ha;
|
||||
}
|
||||
T await_resume() {
|
||||
if (!destroyed) {
|
||||
h.promise().result_ready = false;
|
||||
return std::move(h.promise().ret_value);
|
||||
}
|
||||
return std::move(ret_value);
|
||||
}
|
||||
|
||||
bool destroyed = false;
|
||||
T ret_value;
|
||||
std::coroutine_handle<promise_type> h;
|
||||
};
|
||||
|
||||
enum class AwaitableType {
|
||||
kUnknown = 0,
|
||||
kUartRx = 1,
|
||||
|
||||
Reference in New Issue
Block a user