qubit_atomic/atomic/arc_atomic.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9
10//! # Shared Atomic Wrapper
11//!
12//! Provides [`ArcAtomic<T>`], a convenience wrapper around `Arc<Atomic<T>>`.
13//!
14//! # Author
15//!
16//! Haixing Hu
17
18use std::fmt;
19use std::ops::Deref;
20use std::sync::Arc;
21
22use super::atomic::Atomic;
23use super::atomic_value::AtomicValue;
24
25/// Shared-owner wrapper around [`Atomic<T>`].
26///
27/// This type is a convenience newtype for `Arc<Atomic<T>>`. Cloning an
28/// [`ArcAtomic`] clones the shared owner handle, so all clones operate on the
29/// same underlying atomic container.
30///
31/// Use [`Atomic<T>`] when ownership stays local, and use [`ArcAtomic<T>`] when
32/// the same atomic value must be shared across threads or components.
33///
34/// # Example
35///
36/// ```rust
37/// use qubit_atomic::ArcAtomic;
38///
39/// let counter = ArcAtomic::new(0usize);
40/// let shared = counter.clone();
41///
42/// shared.fetch_inc();
43/// assert_eq!(counter.load(), 1);
44/// assert_eq!(counter.strong_count(), 2);
45/// ```
46pub struct ArcAtomic<T>
47where
48 T: AtomicValue,
49{
50 /// Shared owner of the underlying atomic container.
51 inner: Arc<Atomic<T>>,
52}
53
54impl<T> ArcAtomic<T>
55where
56 T: AtomicValue,
57{
58 /// Creates a new shared atomic value.
59 ///
60 /// # Parameters
61 ///
62 /// * `value` - The initial value stored in the atomic container.
63 ///
64 /// # Returns
65 ///
66 /// A shared atomic wrapper initialized to `value`.
67 #[inline]
68 pub fn new(value: T) -> Self {
69 Self::from_atomic(Atomic::new(value))
70 }
71
72 /// Wraps an existing [`Atomic<T>`] in an [`Arc`].
73 ///
74 /// # Parameters
75 ///
76 /// * `atomic` - The atomic container to share.
77 ///
78 /// # Returns
79 ///
80 /// A shared atomic wrapper owning `atomic`.
81 #[inline]
82 pub fn from_atomic(atomic: Atomic<T>) -> Self {
83 Self {
84 inner: Arc::new(atomic),
85 }
86 }
87
88 /// Wraps an existing shared atomic container.
89 ///
90 /// # Parameters
91 ///
92 /// * `inner` - The shared atomic container to wrap.
93 ///
94 /// # Returns
95 ///
96 /// A wrapper around `inner`.
97 #[inline]
98 pub fn from_arc(inner: Arc<Atomic<T>>) -> Self {
99 Self { inner }
100 }
101
102 /// Returns the underlying [`Arc`] without cloning it.
103 ///
104 /// # Returns
105 ///
106 /// A shared reference to the underlying `Arc<Atomic<T>>`.
107 #[inline]
108 pub fn as_arc(&self) -> &Arc<Atomic<T>> {
109 &self.inner
110 }
111
112 /// Consumes this wrapper and returns the underlying [`Arc`].
113 ///
114 /// # Returns
115 ///
116 /// The underlying `Arc<Atomic<T>>`.
117 #[inline]
118 pub fn into_arc(self) -> Arc<Atomic<T>> {
119 self.inner
120 }
121
122 /// Returns the number of strong [`Arc`] owners.
123 ///
124 /// # Returns
125 ///
126 /// The current strong reference count of the shared atomic container.
127 #[inline]
128 pub fn strong_count(&self) -> usize {
129 Arc::strong_count(&self.inner)
130 }
131}
132
133impl<T> Clone for ArcAtomic<T>
134where
135 T: AtomicValue,
136{
137 /// Clones the shared owner handle.
138 ///
139 /// # Returns
140 ///
141 /// A new wrapper pointing to the same underlying atomic container.
142 #[inline]
143 fn clone(&self) -> Self {
144 Self {
145 inner: Arc::clone(&self.inner),
146 }
147 }
148}
149
150impl<T> Deref for ArcAtomic<T>
151where
152 T: AtomicValue,
153{
154 type Target = Atomic<T>;
155
156 /// Dereferences to the underlying [`Atomic<T>`].
157 ///
158 /// # Returns
159 ///
160 /// A shared reference to the atomic container.
161 #[inline]
162 fn deref(&self) -> &Self::Target {
163 self.inner.as_ref()
164 }
165}
166
167impl<T> From<T> for ArcAtomic<T>
168where
169 T: AtomicValue,
170{
171 /// Converts an initial value into a shared atomic wrapper.
172 ///
173 /// # Parameters
174 ///
175 /// * `value` - The initial value stored in the atomic container.
176 ///
177 /// # Returns
178 ///
179 /// A shared atomic wrapper initialized to `value`.
180 #[inline]
181 fn from(value: T) -> Self {
182 Self::new(value)
183 }
184}
185
186impl<T> From<Atomic<T>> for ArcAtomic<T>
187where
188 T: AtomicValue,
189{
190 /// Converts an atomic container into a shared atomic wrapper.
191 ///
192 /// # Parameters
193 ///
194 /// * `atomic` - The atomic container to share.
195 ///
196 /// # Returns
197 ///
198 /// A shared atomic wrapper owning `atomic`.
199 #[inline]
200 fn from(atomic: Atomic<T>) -> Self {
201 Self::from_atomic(atomic)
202 }
203}
204
205impl<T> From<Arc<Atomic<T>>> for ArcAtomic<T>
206where
207 T: AtomicValue,
208{
209 /// Converts an existing shared atomic container into its wrapper.
210 ///
211 /// # Parameters
212 ///
213 /// * `inner` - The shared atomic container to wrap.
214 ///
215 /// # Returns
216 ///
217 /// A wrapper around `inner`.
218 #[inline]
219 fn from(inner: Arc<Atomic<T>>) -> Self {
220 Self::from_arc(inner)
221 }
222}
223
224impl<T> fmt::Debug for ArcAtomic<T>
225where
226 T: AtomicValue + fmt::Debug,
227{
228 /// Formats the current value and sharing state for debugging.
229 ///
230 /// # Parameters
231 ///
232 /// * `f` - The formatter receiving the debug representation.
233 ///
234 /// # Returns
235 ///
236 /// A formatting result from the formatter.
237 #[inline]
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 f.debug_struct("ArcAtomic")
240 .field("value", &self.load())
241 .field("strong_count", &self.strong_count())
242 .finish()
243 }
244}
245
246impl<T> fmt::Display for ArcAtomic<T>
247where
248 T: AtomicValue + fmt::Display,
249{
250 /// Formats the currently loaded value with display formatting.
251 ///
252 /// # Parameters
253 ///
254 /// * `f` - The formatter receiving the displayed value.
255 ///
256 /// # Returns
257 ///
258 /// A formatting result from the formatter.
259 #[inline]
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 write!(f, "{}", self.load())
262 }
263}