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/// # Examples
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(always)]
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(always)]
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    #[must_use]
103    #[inline(always)]
104    pub fn as_arc(&self) -> &Arc<Atomic<T>> {
105        &self.inner
106    }
107
108    /// Consumes this wrapper and returns the underlying [`Arc`].
109    ///
110    /// # Returns
111    ///
112    /// The underlying `Arc<Atomic<T>>`.
113    #[inline(always)]
114    pub fn into_arc(self) -> Arc<Atomic<T>> {
115        self.inner
116    }
117
118    /// Returns the number of strong [`Arc`] owners.
119    ///
120    /// # Returns
121    ///
122    /// The current strong reference count of the shared atomic container.
123    #[must_use]
124    #[inline(always)]
125    pub fn strong_count(&self) -> usize {
126        Arc::strong_count(&self.inner)
127    }
128}
129
130impl<T> Clone for ArcAtomic<T>
131where
132    T: AtomicValue,
133{
134    /// Clones the shared owner handle.
135    ///
136    /// # Returns
137    ///
138    /// A new wrapper pointing to the same underlying atomic container.
139    #[inline(always)]
140    fn clone(&self) -> Self {
141        Self {
142            inner: Arc::clone(&self.inner),
143        }
144    }
145}
146
147impl<T> Deref for ArcAtomic<T>
148where
149    T: AtomicValue,
150{
151    type Target = Atomic<T>;
152
153    /// Dereferences to the underlying [`Atomic<T>`].
154    ///
155    /// # Returns
156    ///
157    /// A shared reference to the atomic container.
158    #[inline(always)]
159    fn deref(&self) -> &Self::Target {
160        self.inner.as_ref()
161    }
162}
163
164impl<T> From<T> for ArcAtomic<T>
165where
166    T: AtomicValue,
167{
168    /// Converts an initial value into a shared atomic wrapper.
169    ///
170    /// # Parameters
171    ///
172    /// * `value` - The initial value stored in the atomic container.
173    ///
174    /// # Returns
175    ///
176    /// A shared atomic wrapper initialized to `value`.
177    #[inline(always)]
178    fn from(value: T) -> Self {
179        Self::new(value)
180    }
181}
182
183impl<T> From<Atomic<T>> for ArcAtomic<T>
184where
185    T: AtomicValue,
186{
187    /// Converts an atomic container into a shared atomic wrapper.
188    ///
189    /// # Parameters
190    ///
191    /// * `atomic` - The atomic container to share.
192    ///
193    /// # Returns
194    ///
195    /// A shared atomic wrapper owning `atomic`.
196    #[inline(always)]
197    fn from(atomic: Atomic<T>) -> Self {
198        Self::from_atomic(atomic)
199    }
200}
201
202impl<T> From<Arc<Atomic<T>>> for ArcAtomic<T>
203where
204    T: AtomicValue,
205{
206    /// Converts an existing shared atomic container into its wrapper.
207    ///
208    /// # Parameters
209    ///
210    /// * `inner` - The shared atomic container to wrap.
211    ///
212    /// # Returns
213    ///
214    /// A wrapper around `inner`.
215    #[inline(always)]
216    fn from(inner: Arc<Atomic<T>>) -> Self {
217        Self::from_arc(inner)
218    }
219}
220
221impl<T> fmt::Debug for ArcAtomic<T>
222where
223    T: AtomicValue + fmt::Debug,
224{
225    /// Formats the current value and sharing state for debugging.
226    ///
227    /// # Parameters
228    ///
229    /// * `f` - The formatter receiving the debug representation.
230    ///
231    /// # Returns
232    ///
233    /// A formatting result from the formatter.
234    #[inline]
235    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236        f.debug_struct("ArcAtomic")
237            .field("value", &self.load())
238            .field("strong_count", &self.strong_count())
239            .finish()
240    }
241}
242
243impl<T> fmt::Display for ArcAtomic<T>
244where
245    T: AtomicValue + fmt::Display,
246{
247    /// Formats the currently loaded value with display formatting.
248    ///
249    /// # Parameters
250    ///
251    /// * `f` - The formatter receiving the displayed value.
252    ///
253    /// # Returns
254    ///
255    /// A formatting result from the formatter.
256    #[inline]
257    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258        write!(f, "{}", self.load())
259    }
260}