我在Clang的Coroutine TS的当前实现中起到了一点作用,我偶然发现了asio无堆栈协程实现。它们被描述为Portable Stackless Coroutines in One* Header。 主要处理异步代码,我也想尝试一下。
main
函数内部的协程块应等待函数foo
中产生的线程异步设置的结果。但是,我不确定在线程设置值后如何让执行在<1>
点(在yield
表达式之后)继续执行。
使用协程TS,我会称呼coroutine_handle
,但是boost::asio::coroutine
似乎无法通话。
使用boost::asio::coroutine
甚至有可能吗?
#include <thread>
#include <chrono>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/yield.hpp>
#include <cstdio>
using namespace std::chrono_literals;
using coroutine = boost::asio::coroutine;
void foo(coroutine & coro, int & result) {
std::thread([&](){
std::this_thread::sleep_for(1s);
result = 3;
// how to resume at <1>?
}).detach();
}
int main(int, const char**) {
coroutine coro;
int result;
reenter(coro) {
// Wait for result
yield foo(coro, result);
// <1>
std::printf("%d\n", result);
}
std::thread([](){
std::this_thread::sleep_for(2s);
}).join();
return 0;
}
感谢您的帮助
答案 0 :(得分:0)
首先,将无堆栈协程更好地描述为可恢复功能。您当前遇到的问题是使用main。如果您将逻辑提取到单独的函子,则有可能:
class task; // Forward declare both because they should know about each other
void foo(task &task, int &result);
// Common practice is to subclass coro
class task : coroutine {
// All reused variables should not be local or they will be
// re-initialized
int result;
void start() {
// In order to actually begin, we need to "invoke ourselves"
(*this)();
}
// Actual task implementation
void operator()() {
// Reenter actually manages the jumps defined by yield
// If it's executed for the first time, it will just run from the start
// If it reenters (aka, yield has caused it to stop and we re-execute)
// it will jump to the right place for you
reenter(this) {
// Yield will store the current location, when reenter
// is ran a second time, it will jump past yield for you
yield foo(*this, result);
std::printf("%d\n", result)
}
}
}
// Our longer task
void foo(task & t, int & result) {
std::thread([&](){
std::this_thread::sleep_for(1s);
result = 3;
// The result is done, reenter the task which will go to just after yield
// Keep in mind this will now run on the current thread
t();
}).detach();
}
int main(int, const char**) {
task t;
// This will start the task
t.start();
std::thread([](){
std::this_thread::sleep_for(2s);
}).join();
return 0;
}
请注意,不可能从子函数中屈服。这是无堆栈协程的局限性。
工作原理:
现在“启动”完成了,您启动了另一个线程来等待。同时,foo的线程完成其睡眠并再次调用您的任务。现在:
foo线程现在已完成,main可能仍在等待第二个线程。