def*_*ode 9 c++ cross-platform coroutine c++11
我遇到的所有协程实现都使用汇编或检查内容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;
};
Run Code Online (Sandbox Code Playgroud)
更新 2013-05-13这些天有Boost Coroutine(基于Boost Context构建,尚未在所有目标平台上实现,但很可能在所有主要平台上得到支持,而不是更晚).
我不知道无堆栈协程是否符合您的预期用途,但我建议您在这里查看它们:
Asio还有一个基于单个(IIRC)简单预处理器宏的协同过程"仿真"模型,结合了一些狡猾设计的模板工具,这些工具非常接近编译器支持_stack-less co过程.
示例HTTP Server 4是该技术的示例.
Boost Asio(Kohlhoff)的作者在他的博客上解释了这个机制和样本:无底座协程的盆栽指南
一定要查找该系列中的其他帖子!
有关协程支持的C++标准提案 - N3708由Oliver Kowalke(Boost.Coroutine的作者)和Goodspeed编写.
我想最终这将是最终的干净解决方案(如果它发生......)因为我们没有来自C++编译器的堆栈交换支持,协程当前需要低级别(通常是汇编级别,或setjmp/longjmp)hack,并且这是C++的抽象范围.然后实现是脆弱的,需要编译器的帮助才能健壮.
例如,设置协程上下文的堆栈大小真的很难,如果你溢出堆栈,你的程序将被静默地破坏.或者如果你很幸运会崩溃.分段堆栈似乎可以帮助这一点,但同样,这需要编译器级别的支持.
如果它成为标准,编译器编写者将会照顾.但在那之前,Boost.Coroutine对我来说是C++中唯一实用的解决方案.
在C中,libtask由Russ Cox(他是Go团队的成员)撰写.libtask效果很好,但似乎不再维护.
PS如果有人知道如何支持标准提案,请告诉我.我真的支持这个提议.