The foundation: thread, mutex + lock_guard, condition_variable, atomic with the memory model. Idiom: data owned by locks, never locks sprinkled over data.
std::lock_guard<std::mutex> lk(m_);
queue_.push(std::move(job));
cv_.notify_one();
The foundation: thread, mutex + lock_guard, condition_variable, atomic with the memory model. Idiom: data owned by locks, never locks sprinkled over data.
std::lock_guard<std::mutex> lk(m_);
queue_.push(std::move(job));
cv_.notify_one();
shared_timed_mutex + shared_lock introduce reader/writer locking; std::make_unique removes a race-y allocation pattern in thread args.
shared_mutex proper, scoped_lock for deadlock-free multi-lock acquisition, and hardware_destructive_interference_size for false-sharing-aware layout.
std::scoped_lock lk(m1, m2); // locks both, deadlock-free order
Structured-shutdown era: jthread auto-joins, stop_token standardizes cooperative cancellation; latch/barrier/counting_semaphore arrive; atomics get futex-style wait/notify and atomic_ref.
std::jthread worker([](std::stop_token st) {
while (!st.stop_requested()) pump();
}); // destructor requests stop, then joins
Quiet release for threads themselves; the async story moves to coroutines and (incoming) senders. std::print output is at least not interleaved mid-argument.
Lock-free reclamation becomes standard — std::hazard_pointer and RCU (std::rcu_obj_base, rcu_synchronize) — plus atomic::fetch_max/fetch_min. Structured concurrency itself lives in std::execution.
// reader side, RCU:
std::scoped_lock rl(std::rcu_default_domain());
auto* snap = table.load(std::memory_order_acquire);
use(*snap); // reclaimed only after all readers pass a quiescent state
Direction: concurrent data structures (queues, P0260 line), executors follow-on work, and more lock-free building blocks.
C++26 per the final working draft; C++29 rows are proposals and direction, not adopted features.