Skip to main content

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}