Skip to content

Latest commit

 

History

History
executable file
·
155 lines (120 loc) · 5.16 KB

coroutine.md

File metadata and controls

executable file
·
155 lines (120 loc) · 5.16 KB

コルーチン

コルーチンには、Boost.Coroutine2を使用する。

インデックス

コルーチンは、プログラミングの構造の一種である。また、コルーチンは特別な種類の制御フローを提供する言語レベルの構成要素と見なすことができる。通常、サブルーチン(関数)を呼びだすとそれが終了するまで呼びだし元に制御は帰らないが、コルーチンは一旦処理を中断し、制御を呼びだし元に戻した後に、中断したポイントの続きから処理を再開できる。

Boost.Coroutine2 では、coroutine<>::pull_typecoroutine<>::pull_typeをセットで用いる。これらの非対称コルーチン型は、単方向のデータ転送を提供している。また、Boost.Coroutine2 の実装には、コンテキストの切り替えに Boost.Context を使用しており、ライブラリのリンクが必要である。

次の例では、コルーチン関数からデータを転送している。

#include <boost/coroutine2/coroutine.hpp>
#include <iostream>

typedef boost::coroutines2::coroutine<int> coro_t;

void func(coro_t::push_type& sink) 
{
  std::cout << 2 << " ";
  sink(3); // {3}をメインコンテキストに戻す
  std::cout << 5 << " ";
  sink(6); // {6}をメインコンテキストに戻す
}

int main() 
{
  std::cout << 1 << " ";
  coro_t::pull_type source(func); // コンストラクタがコルーチン関数に入る
    
  if (source) //プルコルーチンが有効かどうかをテストする
    std::cout << source.get() << " "; // データ値にアクセス
    
  std::cout << 4 << " ";
    
  if (source) {
    source(); // コンテキストスイッチ
    std::cout << source.get() << " "; // データ値にアクセス
  }
  
  std::cout << 7;
}

実行結果:

1 2 3 4 5 6 7

実行制御がコルーチン関数から返された後のコルーチンの状態は、coroutine<>::pull_type::operator boolで確認でき、コルーチンがまだ有効であればtrueを返す。(trueならばコルーチン関数は終了していない)。また、最初のテンプレートパラメータがvoidでない限り、trueはデータ値が利用可能であることも意味する。

#include <boost/coroutine2/coroutine.hpp>
#include <iostream>

typedef boost::coroutines2::coroutine<int> coro_t;

void func(coro_t::pull_type& source) 
{
  std::cout << source.get() << " "; // データ値にアクセス
  std::cout << 3 << " ";
  source(); // 制御を戻す
  std::cout << source.get() << " "; 
}

int main() 
{
  std::cout << 1 << " ";
  coro_t::push_type sink(func); // コンストラクタはコルーチン関数に入らない
  sink(2); // {2}をコルーチン関数に push する
  std::cout << 4 << " ";
  sink(5); // {5}をコルーチン関数に push する
  std::cout << 6 << " ";
}

実行結果:

1 2 3 4 5 6

Boost.Coroutine2 は出力反復子と入力反復子を提供している。

入力反復子は、coroutine<>::pull_typeから作成できる。

#include <boost/coroutine2/coroutine.hpp>
#include <iostream>

typedef boost::coroutines2::coroutine<int> coro_t;

int main() 
{
  coro_t::pull_type source(
    [](coro_t::push_type & sink) 
    {
      for (auto i = 0; i < 10; ++i)
        sink(i);
    });

  for (auto i : source)
    std::cout << i <<  " ";
}

実行結果:

0 1 2 3 4 5 6 7 8 9 

出力反復子は、coroutine<>::push_typeから作成できる。

#include <boost/coroutine2/coroutine.hpp>
#include <algorithm>
#include <iostream>

typedef boost::coroutines2::coroutine<int> coro_t;

int main() 
{
  coro_t::push_type sink(
    [&](coro_t::pull_type& source){
      while(source){
        std::cout << source.get() <<  " ";
        source();
      }
    });

  std::vector<int> v{1, 1, 2, 3, 5};
  std::copy(begin(v), end(v), begin(sink));
}

実行結果:

1 1 2 3 5