3 Now that we've decided the layout for our implementation of `Arc`, let's create
6 ## Constructing the Arc
8 We'll first need a way to construct an `Arc<T>`.
10 This is pretty simple, as we just need to box the `ArcInner<T>` and get a
11 `NonNull<T>` pointer to it.
13 <!-- ignore: simplified code -->
16 pub fn new(data: T) -> Arc<T> {
17 // We start the reference count at 1, as that first reference is the
19 let boxed = Box::new(ArcInner {
20 rc: AtomicUsize::new(1),
24 // It is okay to call `.unwrap()` here as we get a pointer from
25 // `Box::into_raw` which is guaranteed to not be null.
26 ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
35 Since we're building a concurrency primitive, we'll need to be able to send it
36 across threads. Thus, we can implement the `Send` and `Sync` marker traits. For
37 more information on these, see [the section on `Send` and
38 `Sync`](../send-and-sync.md).
41 * You can only get a mutable reference to the value inside an `Arc` if and only
42 if it is the only `Arc` referencing that data (which only happens in `Drop`)
43 * We use atomics for the shared mutable reference counting
45 <!-- ignore: simplified code -->
47 unsafe impl<T: Sync + Send> Send for Arc<T> {}
48 unsafe impl<T: Sync + Send> Sync for Arc<T> {}
51 We need to have the bound `T: Sync + Send` because if we did not provide those
52 bounds, it would be possible to share values that are thread-unsafe across a
53 thread boundary via an `Arc`, which could possibly cause data races or
56 For example, if those bounds were not present, `Arc<Rc<u32>>` would be `Sync` or
57 `Send`, meaning that you could clone the `Rc` out of the `Arc` to send it across
58 a thread (without creating an entirely new `Rc`), which would create data races
59 as `Rc` is not thread-safe.
61 ## Getting the `ArcInner`
63 To dereference the `NonNull<T>` pointer into a `&T`, we can call
64 `NonNull::as_ref`. This is unsafe, unlike the typical `as_ref` function, so we
65 must call it like this:
67 <!-- ignore: simplified code -->
69 unsafe { self.ptr.as_ref() }
72 We'll be using this snippet a few times in this code (usually with an associated
75 This unsafety is okay because while this `Arc` is alive, we're guaranteed that
76 the inner pointer is valid.
80 Alright. Now we can make `Arc`s (and soon will be able to clone and destroy them correctly), but how do we get
83 What we need now is an implementation of `Deref`.
85 We'll need to import the trait:
87 <!-- ignore: simplified code -->
92 And here's the implementation:
94 <!-- ignore: simplified code -->
96 impl<T> Deref for Arc<T> {
99 fn deref(&self) -> &T {
100 let inner = unsafe { self.ptr.as_ref() };
106 Pretty simple, eh? This simply dereferences the `NonNull` pointer to the
107 `ArcInner<T>`, then gets a reference to the data inside.
111 Here's all the code from this section:
113 <!-- ignore: simplified code -->
118 pub fn new(data: T) -> Arc<T> {
119 // We start the reference count at 1, as that first reference is the
121 let boxed = Box::new(ArcInner {
122 rc: AtomicUsize::new(1),
126 // It is okay to call `.unwrap()` here as we get a pointer from
127 // `Box::into_raw` which is guaranteed to not be null.
128 ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
129 phantom: PhantomData,
134 unsafe impl<T: Sync + Send> Send for Arc<T> {}
135 unsafe impl<T: Sync + Send> Sync for Arc<T> {}
138 impl<T> Deref for Arc<T> {
141 fn deref(&self) -> &T {
142 let inner = unsafe { self.ptr.as_ref() };