boost::asyncを使って非同期のタスクを実行することができるのだけど、引数や戻り値の有り無し、タスクがメンバ関数だった時の構文を忘れがちなのでまとめておく
目次
引数も戻り値もない場合
#include <stdio.h> #include <string> #include <iostream> #include <boost/thread.hpp> #include <boost/thread/future.hpp> // 引数も戻り値もないタスク void printHelloTask() { std::cout << "Hello" << std::endl; } int main () { //タスク投入 boost::unique_future<void> f1 = boost::async(boost::launch::async, printHelloTask); //タスク完了待ち f1.wait(); }
boost::asyncのコンストラクタの第一引数はローンチポリシーで、boost::launch::asyncを渡した場合にはスレッドが作られてそこでタスクが実行されます。
第二引数は実行するタスクを渡します。
実行するタスクに引数も戻り値もない場合は単純です。
戻り値がある場合
#include <stdio.h> #include <string> #include <iostream> #include <boost/thread.hpp> #include <boost/thread/future.hpp> // 戻り値があるタスク std::string returnStringTask() { return "Good Morning"; } int main () { //タスク投入 boost::unique_future<std::string> f3 = boost::async( boost::launch::async, returnStringTask); //タスク完了待ち f3.wait(); //タスクの戻り値を取得 std::cout << f3.get() << std::endl; return 0; }
戻り値がある場合もほぼ同じです。
ただboost::asyncの戻り値のfutureのテンプレート引数にreturnStringTaskの戻り値のstd::stringを指定します。
引数がある場合
#include <stdio.h> #include <string> #include <iostream> #include <boost/thread.hpp> #include <boost/thread/future.hpp> // 引数があるタスク void printStringTask(std::string str) { std::cout << str << std::endl; } int main () { //タスク投入 boost::unique_future<void> f2 = boost::async( boost::launch::async, boost::bind(printStringTask, "Hey")); //タスク完了待ち f2.wait(); return 0; }
引数がある場合少しめんどくさくなります。
boost::asyncにはタスクの関数しか渡せませんが同時に引数の文字列”Hey”を渡さなければならないのでboost::bind()を利用して関数と引数をバインドしています。
boost::bind(printStringTask, "Hey"));
引数も戻り値もあるクラスのメンバ関数を呼び出す場合
#include <stdio.h> #include <string> #include <iostream> #include <boost/thread.hpp> #include <boost/thread/future.hpp> class Print { private: const std::string name; public: Print(const std::string& name) : name(name){} //タスク投入を行う関数 void run () { //タスク投入 boost::unique_future<std::string> f4 = boost::async( boost::launch::async, boost::bind( &Print::returnStringTask, this, "Good Evening")); //タスク完了待ち f4.wait(); //タスクの戻り値を取得 std::cout << f4.get() << std::endl; } std::string returnStringTask (std::string message) { return message + " " + name; } }; int main () { Print print("John"); print.run(); return 0; }
もっとも面倒くさいけどでもよく使うパターンです。
基本的には戻り値があるパターン、引数があるパターンの複合ですが、関数名にクラス名を付けてPrint::returnStringTaskとしてアドレスを渡しています。
そして、関数の第一引数としてオブジェクトのthisポインターを渡しています。
boost::bind(&Print::returnStringTask, this, "Good Evening"));