我遇到的所有协程实现都使用汇编或检查jmp_buf
的内容。这样做的问题是它本身不是跨平台的。
我认为以下实现不会陷入不确定的行为或依赖于实现细节。但是我从未遇到过像这样写的协程。
在线程上使用跳远是否存在一些固有的缺陷?
这段代码中有一些隐藏的陷阱吗?
#include <setjmp.h>
#include <thread>
class Coroutine
{
public:
Coroutine( void ) :
m_done( false ),
m_thread( [&](){ this->start(); } )
{ }
~Coroutine( void )
{
std::lock_guard<std::mutex> lock( m_mutex );
m_done = true;
m_condition.notify_one();
m_thread.join();
}
void start( void )
{
if( setjmp( m_resume ) == 0 )
{
std::unique_lock<std::mutex> lock( m_mutex );
m_condition.wait( lock, [&](){ return m_done; } );
}
else
{
routine();
longjmp( m_yield, 1 );
}
}
void resume( void )
{
if( setjmp( m_yield ) == 0 )
{
longjmp( m_resume, 1 );
}
}
void yield( void )
{
if( setjmp( m_resume ) == 0 )
{
longjmp( m_yield, 1 );
}
}
private:
virtual void routine( void ) = 0;
jmp_buf m_resume;
jmp_buf m_yield;
bool m_done;
std::mutex m_mutex;
std::condition_variable m_condition;
std::thread m_thread;
};
最佳答案
我不知道无堆栈协程是否适合您的预期用途,但我建议您在这里查看一下:
Boost Asio:The Proactor Design Pattern: Concurrency Without Threads
Asio还具有基于单个(IIRC)简单预处理器宏的协同过程“仿真”模型,结合了一些经过精心设计的模板工具,这些工具在功能上非常接近编译器对_stack-less协同过程的支持。
示例 HTTP Server 4 是该技术的一个示例。
Boost Asio(Kohlhoff)的作者在其Blog here: A potted guide to stackless coroutines上解释了机理和示例
一定要寻找该系列的其他文章!