Result
这里的result不是协程的返回值,后面给Task::promise_type继承
namespace ASYNCIO_NS {
/*
结果封装类
result()用于获取结果
*/
template<typename T>
struct Result {
constexpr bool has_value() const noexcept {
return std::get_if<std::monostate>(&result_) == nullptr;
}
template<typename R>
constexpr void set_value(R&& value) noexcept {
result_.template emplace<T>(std::forward<R>(value));
}
template<typename R> // for promise_type
constexpr void return_value(R&& value) noexcept {
return set_value(std::forward<R>(value));
}
/*
constexpr T result() && 和 constexpr T result() &
这两个函数声明中的 && 和 & 符号是 cpp11 引入的“引用限定符”(reference qualifiers)。它们用于指定成员函数在对象被左值引用(&)或右值引用(&&)时的行为。
*/
constexpr T result() & {
if (auto exception = std::get_if<std::exception_ptr>(&result_)) {
std::rethrow_exception(*exception);
}
if (auto res = std::get_if<T>(&result_)) {
return *res;
}
throw NoResultError{};
}
constexpr T result() && {
if (auto exception = std::get_if<std::exception_ptr>(&result_)) {
std::rethrow_exception(*exception);
}
if (auto res = std::get_if<T>(&result_)) {
return std::move(*res);
}
throw NoResultError{};
}
void set_exception(std::exception_ptr exception) noexcept { result_ = exception; }
void unhandled_exception() noexcept { result_ = std::current_exception(); }
private:
// std::variant 用于表示可以包含多种类型中的一个的值。它类似于联合体(union)但提供类型安全和额外功能
// reuslt_有三种值:
// T
// std::monostate: 表示一个空状态或者占位符时
// std::exception_ptr 一个指向异常对象的指针,允许在异常被捕获后将异常对象保存起来,以便稍后重新抛出
std::variant<std::monostate, T, std::exception_ptr> result_;
};
// 特化
template<>
struct Result<void> {
constexpr bool has_value() const noexcept {
return result_.has_value();
}
void return_void() noexcept {
result_.emplace(nullptr);
}
void result() {
if (result_.has_value() && *result_ != nullptr) { std::rethrow_exception(*result_); }
}
void set_exception(std::exception_ptr exception) noexcept { result_ = exception; }
void unhandled_exception() noexcept { result_ = std::current_exception(); }
private:
std::optional<std::exception_ptr> result_;
};
}
Task
这里的Task有两个用处:
- 作为协程的返回值
- 给ScheduledTask用
根据Future的定义,因为Task有get_result(),有promise_type,支持移动构造,不支持默认构造。所以Task就是一个Future
Task::promise_type,注意到这里继承了两个类:std::coroutine_handle<promise_type> 和 Result 。 证明promise_type也是一个协程句柄,可以调度,且可以获取结果。
std::coroutine_handle<promise_type>注意以下几个成员函数:
done(): 检查协程是否已完成
resume(): 恢复协程执行
destroy(): 销毁协程
promise(): 访问协程的承诺对象
struct InitialSuspendAwaiter { // 专门用于initial_suspend()
constexpr bool await_ready() const noexcept { return !wait_at_initial_suspend_; }
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
constexpr void await_resume() const noexcept {}
const bool wait_at_initial_suspend_{true};
};
struct FinalAwaiter { // 专门用于final_suspend()
constexpr bool await_ready() const noexcept { return false; } // 要挂起
template<typename Promise>
constexpr void await_suspend(std::coroutine_handle<Promise> h) const noexcept {
if (auto cont = h.promise().continuation_) { // continuation_代表什么???
get_event_loop().call_soon(*cont);
}
}
constexpr void await_resume() const noexcept {}
};
// 这里继承了两个类:std::coroutine_handle<promise_type> 和 Result<R>
struct promise_type: CoroHandle, Result<R> {
// 下面三个都是构造函数
promise_type() = default;
template<typename... Args> // from free function
promise_type(NoWaitAtInitialSuspend, Args&&...): wait_at_initial_suspend_{false} { }
template<typename Obj, typename... Args> // from member function
promise_type(Obj&&, NoWaitAtInitialSuspend, Args&&...): wait_at_initial_suspend_{false} { }
auto initial_suspend() noexcept {
return InitialSuspendAwaiter{wait_at_initial_suspend_};
}
auto final_suspend() noexcept {
return FinalAwaiter {};
}
Task get_return_object() noexcept {
return Task{coro_handle::from_promise(*this)};
}
///
void run() final { // 实现CoroHandle::run() (Handle::run())
coro_handle::from_promise(*this).resume();
}
const std::source_location& get_frame_info() const final { return frame_info_; }
void dump_backtrace(size_t depth = 0) const final {
fmt::print("[{}] {}\n", depth, frame_name());
if (continuation_) { continuation_->dump_backtrace(depth + 1); }
else { fmt::print("\n"); }
}
///
// 成员变量:
const bool wait_at_initial_suspend_ {true}; // 是否在协程初始化时挂起
CoroHandle* continuation_ {}; // ???????????
std::source_location frame_info_{}; // 源码信息(调试用)
};
Task:AwaiterBase
struct AwaiterBase {
constexpr bool await_ready() {
if (self_coro_) [[likely]] // 如果句柄不为空,根据done()返回结果,done就不用挂起了,否则需要挂起
{ return self_coro_.done(); }
return true; // 句柄为空直接返回true,不用挂起
}
template<typename Promise>
void await_suspend(std::coroutine_handle<Promise> resumer) const noexcept {
assert(! self_coro_.promise().continuation_); // continuation_为空
resumer.promise().set_state(Handle::SUSPEND); // 将resumer的状态设置为suspend
self_coro_.promise().continuation_ = &resumer.promise(); // 将Task的handle_的promise的continuation_设置为当前协程的promise
self_coro_.promise().schedule(); // 将Task的handle_加入调度
}
// 少了一个await_resume()
coro_handle self_coro_ {}; // using coro_handle = std::coroutine_handle<promise_type>;
// 这个是Task的handle_
};
namespace ASYNCIO_NS {
struct NoWaitAtInitialSuspend {};
// 使用了 inline 和 constexpr 关键字。这样定义的变量在每个编译单元中都是唯一的,且可以在编译时计算出其值,使得它在编译时就能被完全初始化。
inline constexpr NoWaitAtInitialSuspend no_wait_at_initial_suspend;
template<typename R = void>
struct Task: private NonCopyable {
struct promise_type;
// std::coroutine_handle<> 是 cpp20 标准引入的一个类型,用于表示一个协程的句柄。它是一种轻量级的对象,可以用来恢复、暂停和销毁协程。它的模板参数代表协程的 promise 类型。
using coro_handle = std::coroutine_handle<promise_type>;
template<concepts::Future>
friend struct ScheduledTask;
// 构造函数
explicit Task(coro_handle h) noexcept: handle_(h) {}
// 移动构造函数
Task(Task&& t) noexcept
: handle_(std::exchange(t.handle_, {})) {} // std::exchange提供了一种原子操作,用于交换给定对象的值,并返回该对象原始的值。这个函数的作用类似于 std::swap,但它不会创建临时对象,因此更适用于某些情况下的性能优化
~Task() { destroy(); }
// 返回结果,从promise.result()返回
decltype(auto) get_result() & {
return handle_.promise().result();
}
decltype(auto) get_result() && {
return std::move(handle_.promise()).result();
}
/*
使得Task能跟在co_await表达式后面,即co_await Task
*/
auto operator co_await() const & noexcept {
struct Awaiter: AwaiterBase {
decltype(auto) await_resume() const {
if (! AwaiterBase::self_coro_) [[unlikely]]
{ throw InvalidFuture{}; }
return AwaiterBase::self_coro_.promise().result(); // Task::promise_type继承Result,所以有result()函数
}
};
return Awaiter {handle_};
}
auto operator co_await() const && noexcept {
struct Awaiter: AwaiterBase {
decltype(auto) await_resume() const {
if (! AwaiterBase::self_coro_) [[unlikely]]
{ throw InvalidFuture{}; }
return std::move(AwaiterBase::self_coro_.promise()).result();
}
};
return Awaiter {handle_};
}
bool valid() const { return handle_ != nullptr; }
bool done() const { return handle_.done(); }
private:
void destroy() {
if (auto handle = std::exchange(handle_, nullptr)) {
handle.promise().cancel(); // handle取消调度(CoroHandle::cancel())
handle.destroy(); // std::coroutine_handle<promise_type>::destroy()
}
}
private:
coro_handle handle_; // using coro_handle = std::coroutine_handle<promise_type>; Task所在协程的协程句柄
};
static_assert(concepts::Promise<Task<>::promise_type>);
static_assert(concepts::Future<Task<>>);
}