gpt4 book ai didi

C++ 协程 : call a coroutine function without co_await

转载 作者:行者123 更新时间:2023-11-28 08:34:38 26 4
gpt4 key购买 nike

结构任务修改自https://github.com/Quuxplusone/coro/blob/master/include/coro/gor_task.h .我只是更改suspend_always in Line 18暂停_never。

// test.cpp
#include <exception>
#include <experimental/coroutine>
#include <variant>

template<class T>
struct task {
struct promise_type {
std::variant<std::monostate, T, std::exception_ptr> result_;
std::experimental::coroutine_handle<void> waiter_;

task get_return_object() { return task(this); }
auto initial_suspend() { return std::experimental::suspend_never{}; } // Originally suspend_always
auto final_suspend() {
struct Awaiter {
promise_type *me_;
bool await_ready() { return false; }
void await_suspend(std::experimental::coroutine_handle<void> caller) {
me_->waiter_.resume();
}
void await_resume() {}
};
return Awaiter{this};
}
template<class U>
void return_value(U&& u) {
result_.template emplace<1>(static_cast<U&&>(u));
}
void unhandled_exception() {
result_.template emplace<2>(std::current_exception());
}
};

bool await_ready() { return false; }
void await_suspend(std::experimental::coroutine_handle<void> caller) {
coro_.promise().waiter_ = caller;
coro_.resume();
}
T await_resume() {
if (coro_.promise().result_.index() == 2) {
std::rethrow_exception(std::get<2>(coro_.promise().result_));
}
return std::get<1>(coro_.promise().result_);
}

~task() {
coro_.destroy();
}
private:
using handle_t = std::experimental::coroutine_handle<promise_type>;
task(promise_type *p) : coro_(handle_t::from_promise(*p)) {}
handle_t coro_;
};

#include <stdio.h>

task<int> f2() {
puts("enter f2");
co_return 1;
}

task<int> f1() {
puts("enter f1");
int a = co_await f2();
printf("f2 return: %d\n", a);
co_return a;
}

int main() {
f1();
}
$ clang++ -fcoroutines-ts -std=c++17 -stdlib=libc++ -lc++ -lc++abi test.cpp -o test
$ ./test
enter f1
enter f2
fish: './test' terminated by signal SIGSEGV (Address boundary error)

因为没有 co_await,我希望 f2 return: 1 应该被打印并且程序应该正常退出,但它因段错误而崩溃。为什么以及如何解决此问题?

最佳答案

当协程函数执行 co_await 时,它会停止该函数的执行并将该执行的恢复安排给其他人。这个“其他人”最终取决于被 co_await 处理的表达式、协程函数的 promise 类型以及协程返回的 future 类型。

那么让我们看看这里的控制流。

f2 被调用。它执行,然后通过 co_return 终止。这意味着 f2 的协程句柄是完整的。这也意味着将调用 promise 类型的 final_suspend。好吧,协程机制期望 final_suspend 将返回一个等待类型,您的 task::promise 提供了它。

除了... task::promise::waiter_ 未初始化。这是因为只有await_suspendwaiter_赋值。还没有人对 f2 的返回值进行 co_await 编辑。因此,在此之前,waiter_ 没有值。

因此,当 f2 被调用时,您尝试继续一个充其量为 nullptr 的协程句柄,从而导致崩溃。

如果 final_suspendAwaiter 类型首先检查 waiter_ 是否为 nullptr 会更有意义(这意味着还没有人在等待协程)如果是,则从 await_ready 返回 true

关于C++ 协程 : call a coroutine function without co_await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59434882/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com