ダウンロード サンプルファイル (35.6 KB)
「g++で書かれた(ちょい昔の)LinuxアプリをWindowsにportしたい」って相談事が舞い込んできました。聞けばそのアプリ、スレッドまわりにおなじみpthreadを使ってて、pthreadとWindows-APIとの対応表を作って欲しい、みたいなお話でした。ざっくり元コードを眺めたところほとんどがC++のスレッドサポートライブラリで置き換え可能だったので「C++11なら一本のコードでLinux/Windowsの両方で動くよ」とアドバイスし、6年ほど前に書いたアーティクル:「スレッド・ライブラリひとめぐり」を紹介しておきました。念のために読み返してみたんですけど、ライブラリの概要を駆け足で紹介したために説明が足りてないんですねぇ……。おさらいを兼ねて書き足して置かにゃならんかと。
- こちらと併せてご覧ください:「スレッド・ライブラリひとめぐり」
スレッドを起動する
std::threadを用いたスレッドの生成はpthread_create()やCreateThread()より数十倍(当社比)簡単、関数オブジェクトとそれに渡す引数とをstd::threadのコンストラクタに与えるだけでスレッドが生成され、そのスレッドの中で関数オブジェクトが動き始めます。
#include <thread>
#include <chrono>
#include <string>
#include <iostream>
/*
* フツーの関数
*/
void global_fun(int n) {
using namespace std;
cout << "global_fun: " + to_string(n) + " 秒後に終了します...\n";
this_thread::sleep_for(chrono::seconds(n));
cout << "global_fun: おしまい\n";
}
/*
* ラムダ式
*/
auto lambda_exp = [](int n) {
using namespace std;
cout << "lambda_exp: " + to_string(n) + " 秒後に終了します...\n";
this_thread::sleep_for(chrono::seconds(n));
cout << "lambda_exp: おしまい\n";
};
/*
* メンバ関数
*/
#include <functional>
class Foo {
private:
int bias_;
public:
explicit Foo(int b) : bias_(b) {}
void member_fun(int n) {
using namespace std;
cout << "member_fun: " + to_string(bias_+n) + " 秒後に終了します...\n";
this_thread::sleep_for(chrono::seconds(bias_+n));
cout << "member_fun: おしまい\n";
}
// 関数オブジェクトを返す wrapper
std::function<void(int)> member_fun() {
// this をキャプチャした lambda で wrap する
return [this](int n) { member_fun(n); };
}
};
// おためし
int main() {
using namespace std;
cout << "いろんなタスクからスレッドを作るよ!\n";
thread thr0(global_fun, 2);
thread thr1(lambda_exp, 3);
Foo foo(3);
thread thr2(foo.member_fun(), 1);
cout << "スレッドの終了を待ってます\n";
thr0.join();
thr1.join();
thr2.join();
cout << "ぜんぶおしまい\n";
}

スレッド終了より先にstd::threadがデストラクトされるとstd::terminate()により異常終了しちゃうので、必ずjoin()でスレッドの終了を待つか、あるいはdetach()でスレッドをstd::threadの管理下から外しておきましょう。
#include <thread>
#include <chrono>
#include <string>
#include <iostream>
#include <exception>
void bad_termination() {
std::cerr << "異常終了!!\n";
}
int main() {
using namespace std;
std::set_terminate(bad_termination);
cout << "main:\n";
thread thr([](int n) {
cout << "lambda_exp: " + to_string(n) + " 秒後に終了します...\n";
this_thread::sleep_for(chrono::seconds(n));
cout << "lambda_exp: おしまい\n";
}, 2);
cout << "main:おしまい\n";
// 異常終了を避けたいなら thr.join() : 完了待ち
// さもなくば thr.detach() : 親権放棄 すべし
}

この記事は参考になりましたか?
- C++11:スレッド・ライブラリひとめぐり連載記事一覧
-
- C++11:スレッド・ライブラリひとめぐり【補足編:3】
- C++11:スレッド・ライブラリひとめぐり【補足編:2】
- C++11:スレッド・ライブラリひとめぐり【補足編:1】
- この記事の著者
-
επιστημη(エピステーメー)
C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
