LoginSignup
0
2

More than 3 years have passed since last update.

クラス内部で std::thread を使う

Last updated at Posted at 2020-08-31

環境

$ 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::joinstd::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 を利用)

main.cpp
#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::swapMyClass::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;
}
0
2
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2