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