std::asyncめも

std::asyncなるものがあると聞いたので、とりあえずどんな感じで使えばいいのかをめも。
まずはこちらから。

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
using namespace std;

class Hoge{
public:
  Hoge(){ cout << "Hoge::Hoge()" << endl; }
  ~Hoge(){ cout << "Hoge::~Hoge()" << endl; }

  void operator()(){
    cout << "thread start" << endl;
    this_thread::sleep_for(chrono::seconds(5));
    cout << "thread end" << endl;
  }
};

int main(int argc, char **argv){
  Hoge hoge;

  async(launch::async, ref(hoge)); //これはスレッドの終了を待つ
  cout << "---" << endl;

  auto f = async(launch::async, ref(hoge)); //これはfのデストラクタでスレッドの終了を待つ

  cout << "main end" << endl;
  //f.wait();
  return 0;
}

実行結果

$ ./a.exe
Hoge::Hoge()
thread start
thread end
    • -
thread start main end thread end Hoge::~Hoge()

使い方は、asyncに実行したい関数オブジェクトを渡すだけ。
async(launch::async, ref(hoge));
のように、戻り値を受け取らないように書いた場合は、そこでスレッドの終了を待つみたい。


auto f = async(launch::async, ref(hoge));
のように、戻り値(型はstd::futureになるみたい)を受け取った場合は、std::future::wait()などが用意されてるので、それを使えばスレッドの終了待ちができるみたい。
今回はwait()使ってないけど、fのデストラクタで終了待ちしてくれるみたいでした。


また、スレッドで投げた例外を受け取りたい場合、std::future::get();を使えばいいみたい。

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
using namespace std;

class Hoge{
public:
  Hoge(){ cout << "Hoge::Hoge()" << endl; }
  ~Hoge(){ cout << "Hoge::~Hoge()" << endl; }

  void operator()(){
    cout << "thread start" << endl;
    this_thread::sleep_for(chrono::seconds(5));
    throw 999;
    cout << "thread end" << endl;
  }
};

int main(int argc, char **argv){
  try{
    Hoge hoge;
    auto f = async(launch::async, ref(hoge));
    cout << "---" << endl;
    f.get();
    cout << "---" << endl;
  }catch(int i){
    cout << i << endl;
  }

  cout << "main end" << endl;
  return 0;
}

実行結果

$ ./a.exe
Hoge::Hoge()
    • -
thread start Hoge::~Hoge() 999 main end

f.get();ってやってるところで、例外を受け取ってます。
すると、catch節にいくので、次のcout << "---" << endl;は呼ばれません。
get()は例外の他に、returnの値も受け取ることができるらしいです。


なんかスレッド周りの話が続いてるけど、スレッドおっ立てるのが趣味って訳じゃないです。
今日のめもおしまい。