31
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C++】std::thread についての覚え書き

Posted at

#はじめに
std::threadを利用していて、困った箇所、詰まった箇所がいくつかあったため、覚え書き程度に。

#基本

std::threadを利用しているということは、マルチスレッド処理をしたい!ということであります。
まずは簡単な基本的な使い方から。

sample.cpp
// threadを利用するために必要
#include <thread>

void temp1()
{
     // 何らかの処理
}

void temp2()
{
     // 何らかの処理
}

int main()
{
     std::thread th1(temp1);
     std::thread th2(temp2);

     th1.join();
     th2.join();
     return 0;
}

とりあえず、temp1、temp2をスレッド分けすることにします。

std::threadオブジェクトを生成する際に、コンストラクタには関数ポインタを渡します。

join()関数で実行され、その後実行済みのthreadオブジェクトの中身はemptyになります。
join()した後に、もう一度同じオブジェクトをjoin()すると、怒られます。

sample.cpp
// 省略

void temp(int a)
{
}

int main()
{
     std::thread th(temp, 12);
     th.join();

     return 0;
}

引数がある場合は、関数ポインタの後ろに、引数順に渡してあげましょう。

ここまでが、基本的な使い方であります。

#ちょっと応用

関数ポインタではなくても、ラムダ式を渡すこともできます。

sample.cpp
int main()
{
     std::thread th([&](int a, int b)
     {
          // 処理
     }, 1, 2
     );
     th.join();
     return 0;
}

個人的にはあまり使わないですが、これも可能です。

#メンバ関数でやりたい場合

ここが、自分が少しだけ詰まったところです。

sample.cpp
class Temp
{
private:
    int m_count = 0;
public:
     void Work(){ m_count++; }
}

例えば、TempクラスのWork関数をマルチスレッドで処理したい!としましょう。

sample.cpp
int main()
{
     std::thread th(Temp::Work);
     th.join();
     return 0;
}

もちろん、コレはダメです。
Work関数がstaticなら動きそう?(試してない)

sample.cpp
int main()
{
     Temp temp;
     std::thread th(temp.Work);
     th.join();
     return 0;
}

これは一応動きます。
ですが、tempがnewしたオブジェクトだったり、Workの中身でシングルトンパターンの何かを利用していたりすると、エラーを吐かれることが稀によくありました。

とりあえず、Tempオブジェクトをnewしているということで進めていきます。

sample.cpp
int main()
{
     Temp* temp = new Temp();

     std::thread th(Temp::Work, temp);
     th.join();

     return 0;
}

先程ダメだと言ったばかりの、Temp::Workバージョンの関数ポインタに、引数としてWorkメンバ関数を持っているオブジェクトのポインタを渡してあげます。

これはmainで使っているサンプルですが、何らかのクラス内で、自分のクラスの関数をマルチスレッドにする場合、thisポインタを渡してあげましょう。

sample.cpp
class Temp
{
     void add(){}
public:
     void Work()
     {
          std::thread th(Temp::add, this);
     }
}

こんな感じです。

引数がある場合は、次のようにします。

sample.cpp
class Temp
{
     void add(int a, int b){ a + b; }
public:
     void Work()
     {
          std::thread th(Temp::add, this, 1, 2);
     }
}

メンバ関数ポインタ、オブジェクトポインタ、引数...の順です。

実はこれ以外にもラムダ式を使ってみたり、色々試行錯誤してみましたが、これが正解でした。

これであなたも、マルチスレッドできるね。

#おわりに

困った事が解決したら、とにかくQiitaでもなんでもいいので、文書化して記録として残しましょう。
それで救われる人間も、いるはずです...。

31
22
2

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
31
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?