aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2024-01-02 03:26:37 -0800
committerChris Robinson <[email protected]>2024-01-02 03:26:37 -0800
commit69ac4a4a9d9e0bc8a62b09d939e2a67f83e5544d (patch)
tree3f9e4e70928d4a2d2de96047a8a4ab0f419a97c7
parent70a8cf88041d88c49dcd258587e6b84960752851 (diff)
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.
-rw-r--r--common/atomic.h6
1 files changed, 5 insertions, 1 deletions
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<T*> ptr) noexcept : mPointer{ptr} { }
explicit atomic_unique_ptr(std::unique_ptr<T>&& 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