
boost::threadで引数つき関数を起動
5分ぐらい考え込んでハマってしまったのでメモっとく。
boost::threadのコンストラクタには引数として関数ポインタを指定してその関数でスレッドを作成するということができるんですが、関数へのポインタ以外の引数は指定できないから、そのスレッドに引数を与えてスレッド起動ということができません。
…。えええーっ!!
いやいや、そんなけしからんことがあってたまるか。_beginthreadexだってpthread_createだって引数付きでスレッド起動できるしさぁ。まぁこいつらだってポインタとして引数1個だけど。
で、どうすればいいかって話なんですが、boost::threadのコンストラクタの関数ポインタは、関数ポインタというのは不正確で関数オブジェクトを引数にとるというのが正確なところ。関数ポインタをわたしてもOKなのはたぶん暗黙の型変換とかなんかでしょ、きっと(調べろよ)。
ってなわけで、どうすればいいかというと、
void powawa(int state){
cout << "current state=" << state << endl;
}
int main(int argc, char* argv[]){
int current_state=3;
boost::thread th(&powawa); // current_stateを渡せない!
return 0;
}
みたいなスレッドのpowawa関数は、関数オブジェクトとして書き直して
class powawa{
public:
// コンストラクタ
powawa(int s){ state=s; }
// 関数オブジェクトのoperator()
inline void operator()(){
cout << "current state=" << state << endl;
}
private:
int state;
};
int main(int argc, char* argv[]){
int current_state=3;
powawa powa(current_state); // current_stateをもった関数オブジェクトの作成
boost::thread th(powa); // current_stateをもった関数オブジェクトでスレッド起動
return 0;
}
と、書き直せばステート付き関数オブジェクトによって好きなだけ引数を持たせたスレッドの起動ができる、ということのようだ。
個人的にはあんまり関数オブジェクトクラスは大量生産したくないんだけど、こういう使い方をするものなのかーと考えると、まさに関数をオブジェクトとしてとらえた使い方で、なかなかこれは理に適った使い方だなーと思った今日この頃です。