Skip to main content

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