【发布时间】:2017-12-31 20:43:17
【问题描述】:
我有一个异步函数
void async_foo(A& a, B& b, C&c, function<void(X&, Y&)> callback);
我想在无堆栈协程中使用它,所以我写了
auto coro_foo(A& a, B& b, C& c, X& x) /* -> Y */ {
struct Awaitable {
bool await_ready() const noexcept { return false; }
bool await_suspend(coroutine_handle<> h) {
async_foo(*a_, *b_, *c_, [this, h](X& x, Y& y){
*x_ = std::move(x);
y_ = std::move(y);
h.resume();
});
}
Y await_resume() {
return std::move(y);
}
A* a_; B* b_; C* c_; X* x_; Y y_;
};
return Awaitable{&a, &b, &c, &x};
}
那么我可以这样使用它:
Y y = co_await coro_foo(a, b, c, x);
编译器会将其重写为:
auto e = coro_foo(a, b, c, x);
if (!e.await_ready()) {
<suspend>
if (e.await_suspend(h)) return;
resume-point:
<resume>
}
Y y = e.await_resume();
这样,协程将在暂停时保留a_、b_ 和c_,只需要保留它们直到我们在await_suspend(h) 中获得coroutine_handle。
(顺便说一句,我不确定我是否可以在此处保留对参数的引用。)
如果包装函数可以直接获取coroutine_handle作为参数,效率会高很多。
这可能是一个隐含的论点:
Promise f(coroutine_handle<> h);
co_await f();
或者它可能是一个特殊的关键字参数:
Promise f(coroutine_handle<> h);
f(co_await);
我在这里遗漏了什么吗? (其他的开销不是很大。)
【问题讨论】:
-
我的库,concurrencpp,确实以非常优化的方式很好地处理了期货和协程,请查看:github.com/David-Haim/concurrencpp
-
@DavidHaim 以及如何将它与
asio::async_read或WSARecv等现有API 一起使用?顺便说一句,你可能想更新它,initial_suspend不能返回 bool。 -
您必须编写一个包装器,将
concurrencpp::promise传递给任何boost::async_xxx并返回concurencpp::future。然后你使用普通的co_await。
标签: c++ c++-coroutine