cs431_homework/arc.rs
1//! Thread-safe reference-counting pointers.
2//!
3//! See the [`Arc<T>`][Arc] documentation for more details.
4
5use std::marker::PhantomData;
6use std::ops::Deref;
7use std::ptr::NonNull;
8#[cfg(not(feature = "check-loom"))]
9use std::sync::atomic::{AtomicUsize, Ordering, fence};
10use std::{fmt, mem};
11
12#[cfg(feature = "check-loom")]
13use loom::sync::atomic::{AtomicUsize, Ordering, fence};
14
15const MAX_REFCOUNT: usize = (isize::MAX) as usize;
16
17/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically
18/// Reference Counted'.
19///
20/// The type `Arc<T>` provides shared ownership of a value of type `T`,
21/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
22/// a new `Arc` instance, which points to the same allocation on the heap as the
23/// source `Arc`, while increasing a reference count. When the last `Arc`
24/// pointer to a given allocation is destroyed, the value stored in that allocation (often
25/// referred to as "inner value") is also dropped.
26///
27/// Shared references in Rust disallow mutation by default, and `Arc` is no
28/// exception: you cannot generally obtain a mutable reference to something
29/// inside an `Arc`. If you need to mutate through an `Arc`, use
30/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic]
31/// types.
32///
33/// ## Thread Safety
34///
35/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference
36/// counting. This means that it is thread-safe. The disadvantage is that
37/// atomic operations are more expensive than ordinary memory accesses. If you
38/// are not sharing reference-counted allocations between threads, consider using
39/// [`Rc<T>`] for lower overhead. [`Rc<T>`] is a safe default, because the
40/// compiler will catch any attempt to send an [`Rc<T>`] between threads.
41/// However, a library might choose `Arc<T>` in order to give library consumers
42/// more flexibility.
43///
44/// `Arc<T>` will implement [`Send`] and [`Sync`] as long as the `T` implements
45/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an
46/// `Arc<T>` to make it thread-safe? This may be a bit counter-intuitive at
47/// first: after all, isn't the point of `Arc<T>` thread safety? The key is
48/// this: `Arc<T>` makes it thread safe to have multiple ownership of the same
49/// data, but it doesn't add thread safety to its data. Consider
50/// <code>Arc<[RefCell\<T>]></code>. [`RefCell<T>`] isn't [`Sync`], and if `Arc<T>` was always
51/// [`Send`], <code>Arc<[RefCell\<T>]></code> would be as well. But then we'd have a problem:
52/// [`RefCell<T>`] is not thread safe; it keeps track of the borrowing count using
53/// non-atomic operations.
54///
55/// In the end, this means that you may need to pair `Arc<T>` with some sort of
56/// [`std::sync`] type, usually [`Mutex<T>`][mutex].
57///
58/// # Cloning references
59///
60/// Creating a new reference from an existing reference-counted pointer is done using the
61/// `Clone` trait implemented for [`Arc<T>`][Arc].
62///
63/// ```
64/// use cs431_homework::Arc;
65/// let foo = Arc::new(vec![1.0, 2.0, 3.0]);
66/// // The two syntaxes below are equivalent.
67/// let a = foo.clone();
68/// let b = Arc::clone(&foo);
69/// // a, b, and foo are all Arcs that point to the same memory location
70/// ```
71///
72/// ## `Deref` behavior
73///
74/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
75/// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
76/// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
77/// functions, called using [fully qualified syntax]:
78///
79/// ```
80/// use cs431_homework::Arc;
81///
82/// let my_arc = Arc::new(5);
83/// let my_five = Arc::try_unwrap(my_arc).unwrap();
84/// ```
85///
86/// `Arc<T>`'s implementations of traits like `Clone` may also be called using
87/// fully qualified syntax. Some people prefer to use fully qualified syntax,
88/// while others prefer using method-call syntax.
89///
90/// ```
91/// use cs431_homework::Arc;
92///
93/// let arc = Arc::new(());
94/// // Method-call syntax
95/// let arc2 = arc.clone();
96/// // Fully qualified syntax
97/// let arc3 = Arc::clone(&arc);
98/// ```
99///
100/// [`Rc<T>`]: std::rc::Rc
101/// [clone]: Clone::clone
102/// [mutex]: ../../std/sync/struct.Mutex.html
103/// [rwlock]: ../../std/sync/struct.RwLock.html
104/// [atomic]: core::sync::atomic
105/// [RefCell\<T>]: core::cell::RefCell
106/// [`RefCell<T>`]: core::cell::RefCell
107/// [`std::sync`]: ../../std/sync/index.html
108/// [`Arc::clone(&from)`]: Arc::clone
109/// [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
110///
111/// # Examples
112///
113/// Sharing some immutable data between threads:
114///
115/// ```no_run
116/// use cs431_homework::Arc;
117/// use std::thread;
118///
119/// let five = Arc::new(5);
120///
121/// for _ in 0..10 {
122/// let five = Arc::clone(&five);
123///
124/// thread::spawn(move || {
125/// println!("{five:?}");
126/// });
127/// }
128/// ```
129///
130/// Sharing a mutable [`AtomicUsize`]:
131///
132/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize"
133///
134/// ```no_run
135/// use cs431_homework::Arc;
136/// use std::sync::atomic::{AtomicUsize, Ordering};
137/// use std::thread;
138///
139/// let val = Arc::new(AtomicUsize::new(5));
140///
141/// for _ in 0..10 {
142/// let val = Arc::clone(&val);
143///
144/// thread::spawn(move || {
145/// let v = val.fetch_add(1, Ordering::SeqCst);
146/// println!("{v:?}");
147/// });
148/// }
149/// ```
150///
151/// See the [`rc` documentation][rc_examples] for more examples of reference
152/// counting in general.
153///
154/// [rc_examples]: std::rc#examples
155pub struct Arc<T> {
156 ptr: NonNull<ArcInner<T>>,
157 phantom: PhantomData<ArcInner<T>>,
158}
159
160unsafe impl<T: Sync + Send> Send for Arc<T> {}
161unsafe impl<T: Sync + Send> Sync for Arc<T> {}
162
163impl<T> Arc<T> {
164 fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
165 Self {
166 ptr,
167 phantom: PhantomData,
168 }
169 }
170}
171
172struct ArcInner<T> {
173 count: AtomicUsize,
174 data: T,
175}
176
177unsafe impl<T: Sync + Send> Send for ArcInner<T> {}
178unsafe impl<T: Sync + Send> Sync for ArcInner<T> {}
179
180impl<T> Arc<T> {
181 /// Constructs a new `Arc<T>`.
182 #[inline]
183 pub fn new(data: T) -> Arc<T> {
184 let x = Box::new(ArcInner {
185 count: AtomicUsize::new(1),
186 data,
187 });
188 Self::from_inner(Box::leak(x).into())
189 }
190
191 /// Returns a mutable reference into the given `Arc` if there are
192 /// no other `Arc`. Otherwise, return `None`.
193 ///
194 /// # Examples
195 ///
196 /// ```
197 /// use cs431_homework::Arc;
198 ///
199 /// let mut x = Arc::new(3);
200 /// *Arc::get_mut(&mut x).unwrap() = 4;
201 /// assert_eq!(*x, 4);
202 ///
203 /// let y = Arc::clone(&x);
204 /// assert!(Arc::get_mut(&mut x).is_none());
205 ///
206 /// drop(y);
207 /// assert!(Arc::get_mut(&mut x).is_some());
208 /// ```
209 #[inline]
210 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
211 todo!()
212 }
213
214 // Used in `get_mut` and `make_mut` to check if the given `Arc` is the unique reference to the
215 // underlying data.
216 #[inline]
217 fn is_unique(&mut self) -> bool {
218 todo!()
219 }
220
221 /// Returns a mutable reference into the given `Arc` without any check.
222 ///
223 /// # Safety
224 ///
225 /// Any other `Arc` to the same allocation must not be dereferenced for the duration of the
226 /// returned borrow. Specifically, call to this function must happen-after destruction of all
227 /// the other `Arc` to the same allocation.
228 ///
229 /// # Examples
230 ///
231 /// ```
232 /// use cs431_homework::Arc;
233 ///
234 /// let mut x = Arc::new(String::new());
235 /// unsafe {
236 /// Arc::get_mut_unchecked(&mut x).push_str("foo")
237 /// }
238 /// assert_eq!(*x, "foo");
239 /// ```
240 pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
241 // We are careful to *not* create a reference covering the "count" fields, as
242 // this would alias with concurrent access to the reference counts (e.g. by `Weak`).
243 unsafe { &mut (*this.ptr.as_ptr()).data }
244 }
245
246 /// Gets the number of `Arc`s to this allocation. In addition, synchronize with the update that
247 /// this function reads from.
248 ///
249 /// # Safety
250 ///
251 /// This method by itself is safe, but using it correctly requires extra care.
252 /// Another thread can change the reference count at any time,
253 /// including potentially between calling this method and acting on the result.
254 ///
255 /// # Examples
256 ///
257 /// ```
258 /// use cs431_homework::Arc;
259 ///
260 /// let five = Arc::new(5);
261 /// let _also_five = Arc::clone(&five);
262 ///
263 /// // This assertion is deterministic because we haven't shared
264 /// // the `Arc` between threads.
265 /// assert_eq!(2, Arc::count(&five));
266 /// ```
267 #[inline]
268 pub fn count(this: &Self) -> usize {
269 todo!()
270 }
271
272 #[inline]
273 fn inner(&self) -> &ArcInner<T> {
274 // This unsafety is ok because while this arc is alive we're guaranteed
275 // that the inner pointer is valid. Furthermore, we know that the
276 // `ArcInner` structure itself is `Sync` because the inner data is
277 // `Sync` as well, so we're ok loaning out an immutable pointer to these
278 // contents.
279 unsafe { self.ptr.as_ref() }
280 }
281
282 /// Returns `true` if the two `Arc`s point to the same allocation
283 /// (in a vein similar to `ptr::eq`).
284 ///
285 /// # Examples
286 ///
287 /// ```
288 /// use cs431_homework::Arc;
289 ///
290 /// let five = Arc::new(5);
291 /// let same_five = Arc::clone(&five);
292 /// let other_five = Arc::new(5);
293 ///
294 /// assert!(Arc::ptr_eq(&five, &same_five));
295 /// assert!(!Arc::ptr_eq(&five, &other_five));
296 /// ```
297 #[inline]
298 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
299 this.ptr.as_ptr() == other.ptr.as_ptr()
300 }
301
302 /// Returns the inner value, if the given `Arc` is unique.
303 ///
304 /// Otherwise, an `Err` is returned with the same `Arc` that was passed in.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// use cs431_homework::Arc;
310 ///
311 /// let x = Arc::new(3);
312 /// assert_eq!(Arc::try_unwrap(x).unwrap(), 3);
313 ///
314 /// let x = Arc::new(4);
315 /// let _y = Arc::clone(&x);
316 /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4);
317 /// ```
318 #[inline]
319 pub fn try_unwrap(this: Self) -> Result<T, Self> {
320 todo!()
321 }
322}
323
324impl<T: Clone> Arc<T> {
325 /// Makes a mutable reference into the given `Arc`.
326 ///
327 /// If there are other `Arc` to the same allocation, then `make_mut` will create a new
328 /// allocation and invoke `clone` on the inner value to ensure unique ownership. This is also
329 /// referred to as clone-on-write.
330 ///
331 /// See also `get_mut`, which will fail rather than cloning.
332 ///
333 /// # Examples
334 ///
335 /// ```
336 /// use cs431_homework::Arc;
337 ///
338 /// let mut data = Arc::new(5);
339 ///
340 /// *Arc::make_mut(&mut data) += 1; // Won't clone anything
341 /// let mut other_data = Arc::clone(&data); // Won't clone inner data
342 /// *Arc::make_mut(&mut data) += 1; // Clones inner data
343 /// *Arc::make_mut(&mut data) += 1; // Won't clone anything
344 /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
345 ///
346 /// // Now `data` and `other_data` point to different allocations.
347 /// assert_eq!(*data, 8);
348 /// assert_eq!(*other_data, 12);
349 /// ```
350 #[inline]
351 pub fn make_mut(this: &mut Self) -> &mut T {
352 todo!()
353 }
354}
355
356impl<T> Clone for Arc<T> {
357 /// Makes a clone of the `Arc` pointer.
358 ///
359 /// This creates another pointer to the same allocation, increasing the
360 /// reference count.
361 ///
362 /// # Panics
363 ///
364 /// This panics if the number of `Arc`s is larger than `isize::Max`.
365 ///
366 /// # Examples
367 ///
368 /// ```
369 /// use cs431_homework::Arc;
370 ///
371 /// let five = Arc::new(5);
372 ///
373 /// let _ = Arc::clone(&five);
374 /// ```
375 #[inline]
376 fn clone(&self) -> Arc<T> {
377 todo!()
378 }
379}
380
381impl<T> Deref for Arc<T> {
382 type Target = T;
383
384 #[inline]
385 fn deref(&self) -> &T {
386 &self.inner().data
387 }
388}
389
390impl<T> Drop for Arc<T> {
391 /// Drops the `Arc`.
392 ///
393 /// This will decrement the reference count. If the reference
394 /// count reaches zero, we `drop` the inner value.
395 ///
396 /// # Examples
397 ///
398 /// ```
399 /// use cs431_homework::Arc;
400 ///
401 /// struct Foo;
402 ///
403 /// impl Drop for Foo {
404 /// fn drop(&mut self) {
405 /// println!("dropped!");
406 /// }
407 /// }
408 ///
409 /// let foo = Arc::new(Foo);
410 /// let foo2 = Arc::clone(&foo);
411 ///
412 /// drop(foo); // Doesn't print anything
413 /// drop(foo2); // Prints "dropped!"
414 /// ```
415 fn drop(&mut self) {
416 todo!()
417 }
418}
419
420impl<T: fmt::Display> fmt::Display for Arc<T> {
421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
422 fmt::Display::fmt(&**self, f)
423 }
424}
425
426impl<T: fmt::Debug> fmt::Debug for Arc<T> {
427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428 fmt::Debug::fmt(&**self, f)
429 }
430}
431
432impl<T> fmt::Pointer for Arc<T> {
433 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
434 fmt::Pointer::fmt(&(&**self), f)
435 }
436}