我遇到的所有协程实现都使用汇编或检查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上解释了机理和示例

一定要寻找该系列的其他文章!

07-24 12:41