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