aboutsummaryrefslogtreecommitdiffstats
path: root/common/atomic.h
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 /common/atomic.h
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.
Diffstat (limited to 'common/atomic.h')
-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