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