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