我想知道一种将值从调用者传递到协程的方法。
我的想法: 任何等待者类型都必须提供
await_resume()
函数。这个函数可以向协程内部的co_await
返回一些东西。
是否可以在awaiter内部设置值来将数据传输到协程? 本例中的问题是:我们如何在调用者内部获取等待者对象?
示例:
#include <coroutine>
#include <iostream>
struct ReturnObject {
struct promise_type {
unsigned value_;
ReturnObject get_return_object()
{
return ReturnObject
{
.h_ = std::coroutine_handle<promise_type>::from_promise(*this)
};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void unhandled_exception() {}
};
std::coroutine_handle<promise_type> h_;
operator std::coroutine_handle<promise_type>() const { return h_; }
};
struct MyAwaiter
{
bool suspend;
bool await_ready() const noexcept { return suspend; }
void await_suspend( std::coroutine_handle<> ) const noexcept { std::cout << "My awaiter suspend" << std::endl;}
std::string await_resume() const noexcept { std::cout << "My awaiter resume" << std::endl; return "Test!";}
};
ReturnObject
counter()
{
for (unsigned i = 0;; ++i)
{
std::cout << "i: " << i << std::endl;
std::string ret = co_await MyAwaiter{false};
std::cout << "Ret: " << ret << std::endl;
}
}
int main()
{
std::coroutine_handle<ReturnObject::promise_type> h = counter();
ReturnObject::promise_type &promise = h.promise();
for (int i = 0; i < 3; ++i)
{
std::cout << "Next iteration" << std::endl;
h();
/// how we can get the awaiter object here??? If we can get it, we can modify
/// it to pass data to the coroutine. Is this possible?
}
h.destroy();
}
也许我完全错了,还有其他方法可以将数据从调用者传递到协程。如果是这样:请给我一个提示,最好是给我一个最小的工作示例。
await_suspend
会发送一个 std::coroutine_handle<void>
,您可以重载它来匹配 std::coroutine_handle<ReturnObject::promise_type>
,这样它的 .promise()
成员将返回原始的 Promise 对象。
void await_suspend( std::coroutine_handle<ReturnObject::promise_type> h) noexcept {
std::cout << "My awaiter suspend on ReturnObject" << std::endl;
h.promise().awaiter = this;
}
然后在主程序中就可以使用了。
std::cout << promise.awaiter->data << '\n';
完整示例
#include <coroutine>
#include <iostream>
struct MyAwaiter;
struct ReturnObject {
struct promise_type {
unsigned value_;
ReturnObject get_return_object()
{
return ReturnObject
{
.h_ = std::coroutine_handle<promise_type>::from_promise(*this)
};
}
MyAwaiter* awaiter = nullptr;
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void unhandled_exception() {}
};
std::coroutine_handle<promise_type> h_;
operator std::coroutine_handle<promise_type>() const { return h_; }
};
struct MyAwaiter
{
bool suspend;
bool await_ready() const noexcept { return suspend; }
void await_suspend( std::coroutine_handle<ReturnObject::promise_type> h) noexcept {
std::cout << "My awaiter suspend on ReturnObject" << std::endl;
h.promise().awaiter = this;
}
void await_suspend( std::coroutine_handle<> ) const noexcept { std::cout << "My awaiter suspend" << std::endl;}
std::string data = "foo";
std::string await_resume() const noexcept { std::cout << "My awaiter resume" << std::endl; return "Test!";}
};
ReturnObject
counter()
{
for (unsigned i = 0;; ++i)
{
std::cout << "i: " << i << std::endl;
std::string ret = co_await MyAwaiter{false};
std::cout << "Ret: " << ret << std::endl;
}
}
int main()
{
std::coroutine_handle<ReturnObject::promise_type> h = counter();
ReturnObject::promise_type &promise = h.promise();
for (int i = 0; i < 3; ++i)
{
std::cout << "Next iteration" << std::endl;
h();
std::cout << promise.awaiter->data << '\n';
}
h.destroy();
}