Namespaces
Variants

std:: notify_all_at_thread_exit

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
notify_all_at_thread_exit
(C++11)
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
ヘッダーで定義 <condition_variable>
void notify_all_at_thread_exit ( std:: condition_variable & cond,
std:: unique_lock < std:: mutex > lk ) ;
(C++11以降)

notify_all_at_thread_exit は、指定されたスレッドが完全に終了したこと(すべての thread_local オブジェクトの破棄を含む)を他のスレッドに通知する仕組みを提供します。その動作は以下の通りです:

  • 以前に取得されたロック lk の所有権は内部ストレージに転送されます。
  • 実行環境が変更され、現在のスレッドが終了する際に、条件変数 cond が以下のように通知されるようになります: lk. unlock ( ) ;
    cond. notify_all ( ) ;

暗黙の lk. unlock ( ) は、現在のスレッドに関連付けられた sequenced after すべての thread local storage duration を持つオブジェクトの破棄の後に順序付けられます。

以下のいずれかの条件が満たされる場合、動作は未定義です:

  • lk は呼び出しスレッドによってロックされていません。
  • 他のスレッドも cond で待機中の場合、 lk. mutex ( ) は、それらのスレッドが cond で呼び出した待機関数( wait wait_for wait_until )によってアンロックされたミューテックスとは異なります。

目次

注記

同等の効果は、 std::promise または std::packaged_task によって提供される機能で達成することができます。

提供されたロック lk はスレッドが終了するまで保持されます。この関数が呼び出された後は、他のスレッドが同じロックを取得して cond を待機することはできません。この条件変数を待機しているスレッドが存在する場合、 lk のロックを保持した状態で待機中の条件が満たされていることを確認し、このロックが notify_all_at_thread_exit の呼び出し前に解放および再取得されないようにして、他のスレッドでの偽の起床による混乱を回避してください。

一般的な使用例では、この関数はデタッチされたスレッドによって最後に呼び出されるものです。

パラメータ

cond - スレッド終了時に通知する条件変数
lk - 条件変数 cond に関連付けられたロック

戻り値

(なし)

この部分的なコードフラグメントは、 notify_all_at_thread_exit を使用して、スレッドローカル変数が破棄されている最中にそれらに依存するデータへのアクセスを回避する方法を示しています:

#include <cassert>
#include <condition_variable>
#include <mutex>
#include <string>
#include <thread>
std::mutex m;
std::condition_variable cv;
bool ready = false;
std::string result; // some arbitrary type
void thread_func()
{
    thread_local std::string thread_local_data = "42";
    std::unique_lock<std::mutex> lk(m);
    // assign a value to result using thread_local data
    result = thread_local_data;
    ready = true;
    std::notify_all_at_thread_exit(cv, std::move(lk));
}   // 1. destroy thread_locals;
    // 2. unlock mutex;
    // 3. notify cv.
int main()
{
    std::thread t(thread_func);
    t.detach();
    // do other work
    // ...
    // wait for the detached thread
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{ return ready; });
    // result is ready and thread_local destructors have finished, no UB
    assert(result == "42");
}

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 2140 C++11 notify_all_at_thread_exit の呼び出しは
cond で待機する関数の呼び出しと同期する
同期要件を更新

関連項目

スレッド終了時のみ通知を配信しながら結果を特定の値に設定する
( std::promise<R> の公開メンバ関数)
現在のスレッドが終了した時点でのみ結果が準備完了となるように関数を実行する
( std::packaged_task<R(Args...)> の公開メンバ関数)