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