namespace std {
class jthread;
}
概要
クラスjthread
は、thread
と同じく、新しい実行のスレッド(thread of execution)(以下、単にスレッドとする)の作成/待機/その他操作を行う機構を提供する。このクラスはさらに、実行しているスレッドに対する停止要求を扱う機能や、自動でjoin
操作を行う機能を提供する。
thread
クラスとの違い
- 停止要求のサポート:
jthread
は自身と関連付けられたスレッドに対する停止要求を扱う仕組みを提供する。このために<stop_token>
ヘッダに定義されたクラスを利用する。 - 自動join機能:
jthread
はデストラクタやムーブ代入演算子が呼び出されたとき、もし自身に関連付けられたスレッドが存在する場合は、スレッドの停止要求を作成し、その後join()
を呼び出してスレッドの終了を待機する。そのためthread
クラスと異なり、joinable() == true
であってもデストラクタやムーブ代入演算子を呼び出し可能であり、std::terminate()
は呼び出されない。
メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++20 |
(destructor) |
デストラクタ | C++20 |
operator= |
代入演算子 | C++20 |
swap |
別のjthread と交換する |
C++20 |
joinable |
スレッドに関連付けられているか否かを取得する | C++20 |
join |
スレッドが終了するまで待機する | C++20 |
detach |
スレッドの管理を手放す | C++20 |
get_id |
関連付けられているスレッドのスレッド識別子を取得する | C++20 |
native_handle |
スレッドに関連付けられたネイティブハンドルを取得する[処理系定義] | C++20 |
get_stop_source |
停止要求を作成するためのstop_source オブジェクトを取得する |
C++20 |
get_stop_token |
停止状態を問い合わせるためのstop_token オブジェクトを取得する |
C++20 |
request_stop |
スレッドに対する停止要求を作成する | C++20 |
静的メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
hardware_concurrency |
処理系によりサポートされるスレッド並行数を取得する | C++20 |
メンバ型
名前 | 説明 | 対応バージョン |
---|---|---|
id |
スレッド識別子 (type-alias) | C++20 |
native_handle_type |
ネイティブハンドル型 (type-alias)[処理系定義] | C++20 |
非メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
swap |
2つのjthread オブジェクトを入れ替える |
C++20 |
備考
- 型
native_handle_type
およびメンバ関数native_handle
について、同メンバの存在有無およびその意味は処理系定義となる。 - 型
id
および型native_handle_type
は、thread
クラスで定義しているものと同じものを使用する。
例
基本的な使い方
#include <iostream>
#include <cstdint>
#include <thread>
std::uint64_t sum1 = 0;
std::uint64_t sum2 = 0;
void f1(std::stop_token stoken, std::uint64_t n)
{
sum1 = 0;
for (std::uint64_t i = 1; i < n; ++i) {
if (stoken.stop_requested()) {
// 中断リクエストがきたのでスレッドを終了する
break;
}
sum1 += i;
}
}
void f2(std::uint64_t n)
{
sum2 = 0;
for (std::uint64_t i = 1; i < n; ++i) {
sum2 += i;
}
}
int main()
{
{
// 関数の第1引数がstd::stop_token型である場合、
// スレッドに中断リクエストを送れるようになる
std::jthread t1 {f1, 1'000'000};
std::this_thread::sleep_for(std::chrono::milliseconds{3});
t1.request_stop(); // スレッドの中断要求を発行
// スレッド実行する関数がstd::stop_tokenを受け取らない場合、
// 中断リクエストを使用せず、
// デストラクタで自動的にjoinするスレッドオブジェクトとして使用する
std::jthread t2 {
[] { f2(1'000'000); }
};
} // jthreadのデストラクタでは、中断要求を発行し、スレッドの終了を待機する
std::cout << sum1 << std::endl; // 計算できたところまで表示
std::cout << sum2 << std::endl;
}
48
std::this_thread::sleep_for(std::chrono::milliseconds{3});
#include <iostream>
#include <cstdint>
#include <thread>
std::uint64_t sum1 = 0;
std::uint64_t sum2 = 0;
void f1(std::stop_token stoken, std::uint64_t n)
{
sum1 = 0;
for (std::uint64_t i = 1; i < n; ++i) {
if (stoken.stop_requested()) {
// 中断リクエストがきたのでスレッドを終了する
break;
}
sum1 += i;
}
}
出力例
48458670270
499999500000
stop_callbackと組み合わせる例
#include <cassert>
#include <thread>
int main()
{
int x = 0, y = 0;
std::jthread t([&](std::stop_token st) { x++; });
// スレッドに対する停止要求の作成に合わせて呼び出される
// コールバックを定義する。
std::stop_callback sc { t.get_stop_token(), [&] { y++; }};
assert(y == 0);
// 明示的にjoin()を呼び出さずにtを上書きする。
// このとき、ムーブ代入演算子の呼び出しの中で、
// 自動で停止要求の作成とjoin()の呼び出しが行われる。
t = std::jthread{};
assert(x == 1 && y == 1);
return 0;
}
25
#include <cassert>
#include <thread>
int main()
{
int x = 0, y = 0;
std::jthread t([&](std::stop_token st) { x++; });
// スレッドに対する停止要求の作成に合わせて呼び出される
// コールバックを定義する。
std::stop_callback sc { t.get_stop_token(), [&] { y++; }};
assert(y == 0);
// 明示的にjoin()を呼び出さずにtを上書きする。
// このとき、ムーブ代入演算子の呼び出しの中で、
// 自動で停止要求の作成とjoin()の呼び出しが行われる。
出力
バージョン
言語
- C++20
処理系
- Clang:
- GCC: 10.2.0 ✅
- Visual C++: ??