• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    class
    <thread>

    std::jthread

    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;
    }
    

    出力例

    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;
    }
    

    出力

    バージョン

    言語

    • C++20

    処理系