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}