環境
$ cat /etc/debian_version
9.4
$ g++ --version
g++ (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516
概要
やりたいこと
クラス内部で std::thread
のコンストラクタを呼び出し,好きなタイミングで std::thread::join
を呼び出す
class MyClass
{
public:
MyClass(void)
{
/* std::thread のコンストラクタを呼び出す */
}
void join(void)
{
/* コンストラクタで作られた std::thread のインスタンスの join を呼び出す */
}
};
int main(void)
{
MyClass my_class;
/* 何らかの処理 */
my_class.join();
return 0;
}
std::thread
のコンストラクタを呼び出したらインスタンスのスコープを抜けるまでに std::thread::join
か std::thread::detach
を呼び出さなければならないため,やりたいことを実現するためには std::thread::swap を利用する必要がある.
以下で説明する std::thread::swap
を利用しても実現できるが,初期化子リストを利用したほう無駄のないコードが書ける.
std::thread::swap
引数に指定した thread と *this を入れ替える.
/* cpprefjp - C++日本語リファレンスより */
# include <thread>
int main()
{
std::thread t1([]{ /*...*/ });
std::thread t2;
t1.swap(t2);
t2.join();
return 0;
}
上記のプログラムのように,t1 でコンストラクタを呼び出した後に std::thread::swap
を使うことで t2 で thread を管理できるようになる.
参考:cpprefjp - C++日本語リファレンス | std::thread::swap
例1(std::thread::swap を利用)
# include <thread>
# include <iostream>
class MyClass
{
private:
std::thread m_t;
public:
MyClass(void)
{
std::thread t([] { std::cout << "hello" << std::endl; });
t.swap(m_t);
}
void join(void)
{
m_t.join();
}
};
int main(void)
{
MyClass my_class;
/* 何らかの処理 */
my_class.join();
return 0;
}
$ g++ main.cpp -pthread
$ ./a.out
hello
MyClass のコンストラクタで std::thread
のコンストラクタを呼び出した後に std::thread::swap
で MyClass::m_t
と入れ替えることによって,thread をクラスで管理できるようになる.
この方法には無駄な処理が含まれているため,次の初期化子リストを利用する方法の方が良さそうです.
例2(初期化子リストを利用)
そもそも std::thread::swap
を使わなくてもできるとのご指摘をいただきました(@yumetodo さんありがとうございました).
/* @yumetodo さんのコメントより */
# include <thread>
# include <iostream>
class MyClass
{
private:
std::thread m_t;
public:
MyClass(void) : m_t{[] { std::cout << "hello" << std::endl; }}
{}
void join(void)
{
m_t.join();
}
};
int main(void)
{
MyClass my_class;
/* 何らかの処理 */
my_class.join();
return 0;
}