Безопасные кроссплатформенные сопрограммы

Все реализации сопрограмм, с которыми я сталкивался, используют соберите или проверьте содержимое 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;
};
9
задан deft_code 1 November 2011 в 23:31
поделиться