From 69ac4a4a9d9e0bc8a62b09d939e2a67f83e5544d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 2 Jan 2024 03:26:37 -0800 Subject: Use an atomic exchange to destruct the atomic unique_ptr A relaxed load isn't required to synchronize with other threads. A thread could exchange the held pointer, and a subsequent load is allowed to get either the pre- or post-swap value (it's only required the value be "complete", not junk or some mix of the old and new value). An exchange, however, is guaranteed to synchronize with itself. If an atomic variable has the value 0, for example, with one thread swapping in the value 1 and another the value 2, the two threads are guaranteed to not both get 0 from the swap. --- common/atomic.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/atomic.h b/common/atomic.h index 51ddaa5d..8e75cb0e 100644 --- a/common/atomic.h +++ b/common/atomic.h @@ -41,7 +41,11 @@ public: explicit atomic_unique_ptr(std::nullptr_t) noexcept { } explicit atomic_unique_ptr(gsl::owner ptr) noexcept : mPointer{ptr} { } explicit atomic_unique_ptr(std::unique_ptr&& rhs) noexcept : mPointer{rhs.release()} { } - ~atomic_unique_ptr() { if(auto ptr = mPointer.load(std::memory_order_relaxed)) D{}(ptr); } + ~atomic_unique_ptr() + { + if(auto ptr = mPointer.exchange(nullptr, std::memory_order_relaxed)) + D{}(ptr); + } atomic_unique_ptr& operator=(const atomic_unique_ptr&) = delete; atomic_unique_ptr& operator=(std::nullptr_t) noexcept -- cgit v1.2.3