std::atomic<T>:: wait
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
atomic::wait
(C++20)
|
||||
|
(C++20)
|
||||
|
(C++20)
|
||||
| Constants | ||||
|
(C++17)
|
||||
| Specialized member functions | ||||
|
Specialized for integral,
floating-point (C++20) and pointer types |
||||
|
Specialized for integral and
pointer types only |
||||
|
(C++26)
|
||||
|
(C++26)
|
||||
| Specialized for integral types only | ||||
|
void
wait
(
T old,
std::
memory_order
order
=
std:: memory_order_seq_cst ) const noexcept ; |
(1) |
(since C++20)
(constexpr since C++26) |
|
void
wait
(
T old,
std::
memory_order
order
=
|
(2) | (since C++20) |
Performs atomic waiting operations. Behaves as if it repeatedly performs the following steps:
-
Compare the
value representation
of
this
-
>
load
(
order
)
with that of
old
.
- If those are equal, then blocks until * this is notified by notify_one() or notify_all() , or the thread is unblocked spuriously.
- Otherwise, returns.
These functions are guaranteed to return only if value has changed, even if underlying implementation unblocks spuriously.
If order is not std:: memory_order_relaxed , std:: memory_order_consume , std:: memory_order_acquire or std:: memory_order_seq_cst , the behavior is undefined.
Contents |
Parameters
| old | - |
the value to check the
atomic
's object no longer contains
|
| order | - | memory order constraints to enforce |
Notes
This form of change-detection is often more efficient than simple polling or pure spinlocks.
Due to the ABA problem , transient changes from old to another value and back to old might be missed, and not unblock.
The comparison is bitwise (similar to std::memcmp ); no comparison operator is used. Padding bits that never participate in an object's value representation are ignored.
Example
#include <atomic> #include <chrono> #include <future> #include <iostream> #include <thread> using namespace std::literals; int main() { std::atomic<bool> all_tasks_completed{false}; std::atomic<unsigned> completion_count{}; std::future<void> task_futures[16]; std::atomic<unsigned> outstanding_task_count{16}; // Spawn several tasks which take different amounts of // time, then decrement the outstanding task count. for (std::future<void>& task_future : task_futures) task_future = std::async([&] { // This sleep represents doing real work... std::this_thread::sleep_for(50ms); ++completion_count; --outstanding_task_count; // When the task count falls to zero, notify // the waiter (main thread in this case). if (outstanding_task_count.load() == 0) { all_tasks_completed = true; all_tasks_completed.notify_one(); } }); all_tasks_completed.wait(false); std::cout << "Tasks completed = " << completion_count.load() << '\n'; }
Output:
Tasks completed = 16
See also
|
(C++20)
|
notifies at least one thread waiting on the atomic object
(public member function) |
|
(C++20)
|
notifies all threads blocked waiting on the atomic object
(public member function) |
|
(C++20)
|
notifies a thread blocked in atomic_wait
(function template) |
|
(C++20)
|
notifies all threads blocked in atomic_wait
(function template) |