Skip to main content

qubit_atomic/atomic/
arc_atomic.rs

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