恢复ASIO无堆栈Coroutine
Resume ASIO Stackless Coroutine
在Clang中玩了一点Coroutine TS的当前实现后,我偶然发现了无asio堆栈的协同程序实现。它们被描述为One*Header中的可移植无堆栈子程序。主要处理异步代码时,我也想尝试一下。
main
函数内的协同程序块应等待函数foo
中派生的线程异步设置的结果。然而,我不确定一旦线程设置了值,如何在点<1>
(在yield
表达式之后(继续执行。
使用Coroutine 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("%dn", result);
}
std::thread([](){
std::this_thread::sleep_for(2s);
}).join();
return 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("%dn", 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;
}
请注意,不可能从子函数中屈服。这是无堆栈协程的一个限制。
工作原理:
- yield存储一个唯一的标识符,以便跳转到协程内部
- yield将运行您放在它后面的表达式,应该是异步调用,否则将不会带来什么好处
- 运行后,它将突破可重入块
现在"启动"完成,您可以启动另一个线程等待。同时,foo的线程完成睡眠并再次调用您的任务。现在:
- 重入块将读取协程的状态,以发现它必须跳过foo调用
- 您的任务将继续,打印结果并退出函数,返回到foo线程
foo线程现在已经完成,main可能仍在等待第二个线程。
相关文章:
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 堆栈和队列是否像C++中的数组一样传递?
- 这对"With a stackless coroutine, only the top-level routine may be suspended."意味着什么
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 从堆栈分配的原始指针构造智能指针
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 堆栈中大小变量输入错误 (C++)
- 堆栈问题(平衡表达式问题集)
- C++ 在堆栈中包含多态属性的类对象存储
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 在 C++ 中使用链表进行堆栈
- 变量周围的堆栈'...'已损坏
- 恢复ASIO无堆栈Coroutine