C++11 のスレッドを使ってみよう
##スリープする
std::this_thread
という名前空間(!)からカレントスレッドを操作することができて、
this_thread::sleep_for
を呼ぶとスレッドを一定時間休ませることができます。sleep_for
が取る引数の型は chrono::duration
というテンプレートクラスの値になります。
template <class Rep, class Period = ratio<1> >
class duration;
なにやら難しげですが、同じ chrono
名前空間に hours
, minutes
, seconds
など、単位を表す型が実体化されて typedef
されていますので、これらのコンストラクタに整数を入れれば大丈夫。
例えば1秒間眠りたいときは
this_thread::sleep_for(chrono::seconds(1))
とやります。何気にポータブルに sleep
する方法が今までなかったのでシングルスレッドでも使えそうですね。
##スレッドを生成する
スレッドを作る時は、コンパイラにオプションを渡してマルチスレッドプログラムであることを伝える必要があるかもしれません。g++
なら -pthread
を指定する必要があります。
thread
型のオブジェクトを作ればもうスレッドが出来て走りだします。コンストラクタへの引数は処理内容を表す関数と、その関数へ渡す引数(いくつでも)。
生成したスレッドに合流したい時は、オブジェクトの join
メンバー関数を呼び出します。というか join
しないで終了するとエラーになりました。
void proc(int n)
{
cout << "わたしは" << n << "円です。\n";
}
int main()
{
thread t1(proc, 10);
t1.join();
}
エントリーポイントの関数は関数オブジェクトやラムダでも大丈夫です。
##スリープソートを書いてみる
やっぱり役に立つプログラムを書かなきゃね (ゝω・)v ってことで、スリープソートと呼ばれる巧妙なアルゴリズムを使って、コマンドラインから渡された整数を昇順に並べかえるプログラムを書きます。
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <cstdlib>
using namespace std;
void sleep_and_print(int n)
{
this_thread::sleep_for(chrono::seconds(n));
cout << n << endl;
}
int main(int argc, char *argv[])
{
vector<shared_ptr<thread> > slaves;
for (int i = 1; i < argc; i++)
{
int n = atoi(argv[i]);
shared_ptr<thread> t( new thread(sleep_and_print,n) );
slaves.push_back(t);
}
for (auto t : slaves)
t->join();
}
thread
型はコピーできないのでポインターを使いました。
$ time ./a.out 14 2 9 4
2
4
9
14
real 0m14.005s
user 0m0.006s
sys 0m0.000s
やったね (ゝω・)v