Thread System 0.3.1
High-performance C++20 thread pool with work stealing and DAG scheduling
Loading...
Searching...
No Matches
atomic_shared_ptr.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
11#pragma once
12
13#include <atomic>
14#include <memory>
15
16namespace kcenon::thread {
17
49template<typename T>
51public:
55 atomic_shared_ptr() noexcept = default;
56
61 explicit atomic_shared_ptr(std::shared_ptr<T> ptr) noexcept
62 : ptr_(std::move(ptr)) {}
63
69 : ptr_(other.load()) {}
70
77 if (this != &other) {
78 store(other.load());
79 }
80 return *this;
81 }
82
88 : ptr_(other.exchange(nullptr)) {}
89
96 if (this != &other) {
97 store(other.exchange(nullptr));
98 }
99 return *this;
100 }
101
107 atomic_shared_ptr& operator=(std::shared_ptr<T> ptr) noexcept {
108 store(std::move(ptr));
109 return *this;
110 }
111
119 void store(std::shared_ptr<T> ptr,
120 std::memory_order order = std::memory_order_seq_cst) noexcept {
121#if __cpp_lib_atomic_shared_ptr >= 201711L
122 ptr_.store(std::move(ptr), order);
123#else
124 std::atomic_store_explicit(&ptr_, std::move(ptr), order);
125#endif
126 }
127
136 [[nodiscard]] std::shared_ptr<T> load(
137 std::memory_order order = std::memory_order_seq_cst) const noexcept {
138#if __cpp_lib_atomic_shared_ptr >= 201711L
139 return ptr_.load(order);
140#else
141 return std::atomic_load_explicit(&ptr_, order);
142#endif
143 }
144
151 [[nodiscard]] std::shared_ptr<T> exchange(
152 std::shared_ptr<T> ptr,
153 std::memory_order order = std::memory_order_seq_cst) noexcept {
154#if __cpp_lib_atomic_shared_ptr >= 201711L
155 return ptr_.exchange(std::move(ptr), order);
156#else
157 return std::atomic_exchange_explicit(&ptr_, std::move(ptr), order);
158#endif
159 }
160
173 std::shared_ptr<T>& expected,
174 std::shared_ptr<T> desired,
175 std::memory_order success = std::memory_order_seq_cst,
176 std::memory_order failure = std::memory_order_seq_cst) noexcept {
177#if __cpp_lib_atomic_shared_ptr >= 201711L
178 return ptr_.compare_exchange_weak(expected, std::move(desired), success, failure);
179#else
180 return std::atomic_compare_exchange_weak_explicit(
181 &ptr_, &expected, std::move(desired), success, failure);
182#endif
183 }
184
196 std::shared_ptr<T>& expected,
197 std::shared_ptr<T> desired,
198 std::memory_order success = std::memory_order_seq_cst,
199 std::memory_order failure = std::memory_order_seq_cst) noexcept {
200#if __cpp_lib_atomic_shared_ptr >= 201711L
201 return ptr_.compare_exchange_strong(expected, std::move(desired), success, failure);
202#else
203 return std::atomic_compare_exchange_strong_explicit(
204 &ptr_, &expected, std::move(desired), success, failure);
205#endif
206 }
207
212 [[nodiscard]] operator std::shared_ptr<T>() const noexcept {
213 return load();
214 }
215
221 [[nodiscard]] T& operator*() const noexcept {
222 return *load();
223 }
224
230 [[nodiscard]] T* operator->() const noexcept {
231 return load().get();
232 }
233
237 [[nodiscard]] explicit operator bool() const noexcept {
238 return load() != nullptr;
239 }
240
247 [[nodiscard]] T* get_unsafe() const noexcept {
248 return load().get();
249 }
250
254 void reset() noexcept {
255 store(nullptr);
256 }
257
262 void reset(T* ptr) noexcept {
263 store(std::shared_ptr<T>(ptr));
264 }
265
266private:
267#if __cpp_lib_atomic_shared_ptr >= 201711L
268 std::atomic<std::shared_ptr<T>> ptr_{nullptr};
269#else
270 std::shared_ptr<T> ptr_{nullptr};
271#endif
272};
273
282template<typename T, typename... Args>
283[[nodiscard]] atomic_shared_ptr<T> make_atomic_shared(Args&&... args) {
284 return atomic_shared_ptr<T>(std::make_shared<T>(std::forward<Args>(args)...));
285}
286
287} // namespace kcenon::thread
std::shared_ptr< T > exchange(std::shared_ptr< T > ptr, std::memory_order order=std::memory_order_seq_cst) noexcept
Atomically exchange the value.
bool compare_exchange_weak(std::shared_ptr< T > &expected, std::shared_ptr< T > desired, std::memory_order success=std::memory_order_seq_cst, std::memory_order failure=std::memory_order_seq_cst) noexcept
Atomically compare and exchange (weak)
atomic_shared_ptr & operator=(std::shared_ptr< T > ptr) noexcept
Assign from shared_ptr.
void reset(T *ptr) noexcept
Reset to new value.
void reset() noexcept
Reset to nullptr.
void store(std::shared_ptr< T > ptr, std::memory_order order=std::memory_order_seq_cst) noexcept
Atomically store a new value.
std::shared_ptr< T > load(std::memory_order order=std::memory_order_seq_cst) const noexcept
Atomically load the current value.
atomic_shared_ptr(atomic_shared_ptr &&other) noexcept
Move constructor.
atomic_shared_ptr & operator=(const atomic_shared_ptr &other)
Copy assignment - atomically copies the shared_ptr.
atomic_shared_ptr(const atomic_shared_ptr &other)
Copy constructor - atomically copies the shared_ptr.
T & operator*() const noexcept
Dereference operator.
T * operator->() const noexcept
Member access operator.
bool compare_exchange_strong(std::shared_ptr< T > &expected, std::shared_ptr< T > desired, std::memory_order success=std::memory_order_seq_cst, std::memory_order failure=std::memory_order_seq_cst) noexcept
Atomically compare and exchange (strong)
atomic_shared_ptr & operator=(atomic_shared_ptr &&other) noexcept
Move assignment.
atomic_shared_ptr() noexcept=default
Default constructor - initializes with nullptr.
T * get_unsafe() const noexcept
Get raw pointer (unsafe - for debugging only)
Core threading foundation of the thread system library.
Definition thread_impl.h:17
atomic_shared_ptr< T > make_atomic_shared(Args &&... args)
Make an atomic_shared_ptr with a new object.
STL namespace.