boost/coroutine編_Dxlibの非同期処理をstd::threadやboost/coroutineでやる
boostのcoroutineってライブラリがある。弾幕風とかluaとかにyieldってのがあって(あるよね?)関数を途中で止めて、再開するときはその止めたところから始めるってのが、c++でもできる。
これに関してなんだけど、日本語で他のブログとかにある情報探したんだけど、
古い。もうそのコードでは動かない
仕方ないから本家のサンプルを引っ張ってくる。
Asymmetric coroutine - 1.58.0
はい、さっぱりわからん。けどサンプルを実際に動かすと、たしかにfor文とかで、途中で戻ってくる。再開するときは、もとのループ変数を保持したままだ。
#include<boost/coroutine/all.hpp> #include<iostream> struct X { X(){ std::cout << "X()" << std::endl; } ~X(){ std::cout << "~X()" << std::endl; } }; int main(){ int i = 0; boost::coroutines::asymmetric_coroutine<void>::push_type sink( [&](boost::coroutines::asymmetric_coroutine<void>::pull_type& source){ X x; for (i = 0;; ++i){ std::cout << "fn(): " << i << std::endl; // transfer execution control back to main() source(); } }); sink(); sink(); sink(); sink(); sink(); std::cout << "sink is complete: " << std::boolalpha << !sink << "\n"; return 0; }
output: X() fn(): 0 fn(): 1 fn(): 2 fn(): 3 fn(): 4 fn(): 5 sink is complete: false ~X()
coroutineはスレッドを生成しているわけではないので、変数にvolatileはいらない。(たぶんね。もしかしたら見当違いなこといってるかもしれない。)
boost::coroutines::asymmetric_coroutine<void>::push_type sink( [&](boost::coroutines::asymmetric_coroutine<void>::pull_type& source){ X x; for (i = 0;; ++i){ std::cout << "fn(): " << i << std::endl; // transfer execution control back to main() source(); } });
ミソは、
boost::coroutines::asymmetric_coroutine
と
source()(↑でいうとforループの中)が呼ばれると、処理が戻ってくる。
ということ。それだけ。それさえ知っとけばできる。詳しいことはしらん
#include<boost/coroutine/all.hpp> #include<iostream> std::function<void(boost::coroutines::asymmetric_coroutine<void>::pull_type&)> Cor_generator(int& progress){ return [&](boost::coroutines::asymmetric_coroutine<void>::pull_type& source){ progress = 0; for (int i = 0;; ++i){ std::cout << "fn(): " << i << std::endl; // transfer execution control back to main() progress += 1; source(); } }; } int main(){ int progress; boost::coroutines::asymmetric_coroutine<void>::push_type sink( Cor_generator(progress) ); while (progress < 100){ sink(); } std::cout << "sink is complete: " << std::boolalpha << !sink << "\n"; return 0; }
boost::coroutines::asymmetric_coroutine