table of contents
std::notify_all_at_thread_exit(3) | C++ Standard Libary | std::notify_all_at_thread_exit(3) |
NAME¶
std::notify_all_at_thread_exit - std::notify_all_at_thread_exit
Synopsis¶
Defined in header <condition_variable>
void notify_all_at_thread_exit( std::condition_variable& cond, (since
C++11)
std::unique_lock<std::mutex> lk );
notify_all_at_thread_exit provides a mechanism to notify other threads that a
given
thread has completely finished, including destroying all thread_local
objects. It
operates as follows:
* Ownership of the previously acquired lock lk is transferred to internal
storage.
* The execution environment is modified such that when the current thread
exits,
the condition variable cond is notified as if by lk.unlock();
cond.notify_all();.
The implied lk.unlock() is sequenced after the destruction of all objects
with
thread local storage duration associated with the current thread.
If any of the following conditions is satisfied, the behavior is
undefined:
* lk is not locked by the calling thread.
* If some other threads are also waiting on cond, lk.mutex() is different
from the
mutex unlocked by the waiting functions (wait, wait_for and wait_until)
called
on cond by those threads.
Notes¶
An equivalent effect may be achieved with the facilities provided
by std::promise or
std::packaged_task.
The supplied lock lk is held until the thread exits. Once this function has
been
called, no more threads may acquire the same lock in order to wait on cond.
If some
threads are waiting on this condition variable, ensure that the condition
being
waited for is satisfied while holding the lock on lk, and that this lock is
not
released and reacquired prior to calling notify_all_at_thread_exit to avoid
confusion from spurious wakeups in other threads.
In typical use cases, this function is the last thing called by a detached
thread.
Parameters¶
cond - the condition variable to notify at thread exit
lk - the lock associated with the condition variable cond
Return value¶
(none)
Example¶
This partial code fragment illustrates how
notify_all_at_thread_exit can be used to
avoid accessing data that depends on thread locals while those thread locals
are in
the process of being destructed:
// Run this code
#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");
}
Defect reports
The following behavior-changing defect reports were applied retroactively to
previously published C++ standards.
DR Applied to Behavior as published Correct behavior
the call to notify_all_at_thread_exit updated the
LWG 2140 C++11 synchronized with calls to functions waiting synchronization
on cond requirement
See also¶
sets the result to specific value while delivering the
set_value_at_thread_exit notification only at thread exit
(public member function of std::promise<R>)
executes the function ensuring that the result is ready
make_ready_at_thread_exit only once the current thread exits
(public member function of std::packaged_task<R(Args...)>)
2024.06.10 | http://cppreference.com |