# Base Code Now that we've decided the layout for our implementation of `Arc`, let's create some basic code. ## Constructing the Arc We'll first need a way to construct an `Arc`. This is pretty simple, as we just need to box the `ArcInner` and get a `NonNull` pointer to it. ```rust,ignore impl Arc { pub fn new(data: T) -> Arc { // We start the reference count at 1, as that first reference is the // current pointer. let boxed = Box::new(ArcInner { rc: AtomicUsize::new(1), data, }); Arc { // It is okay to call `.unwrap()` here as we get a pointer from // `Box::into_raw` which is guaranteed to not be null. ptr: NonNull::new(Box::into_raw(boxed)).unwrap(), phantom: PhantomData, } } } ``` ## Send and Sync Since we're building a concurrency primitive, we'll need to be able to send it across threads. Thus, we can implement the `Send` and `Sync` marker traits. For more information on these, see [the section on `Send` and `Sync`](send-and-sync.md). This is okay because: * You can only get a mutable reference to the value inside an `Arc` if and only if it is the only `Arc` referencing that data (which only happens in `Drop`) * We use atomics for the shared mutable reference counting ```rust,ignore unsafe impl Send for Arc {} unsafe impl Sync for Arc {} ``` We need to have the bound `T: Sync + Send` because if we did not provide those bounds, it would be possible to share values that are thread-unsafe across a thread boundary via an `Arc`, which could possibly cause data races or unsoundness. For example, if those bounds were not present, `Arc>` would be `Sync` or `Send`, meaning that you could clone the `Rc` out of the `Arc` to send it across a thread (without creating an entirely new `Rc`), which would create data races as `Rc` is not thread-safe. ## Getting the `ArcInner` To dereference the `NonNull` pointer into a `&T`, we can call `NonNull::as_ref`. This is unsafe, unlike the typical `as_ref` function, so we must call it like this: ```rust,ignore unsafe { self.ptr.as_ref() } ``` We'll be using this snippet a few times in this code (usually with an associated `let` binding). This unsafety is okay because while this `Arc` is alive, we're guaranteed that the inner pointer is valid. ## Deref Alright. Now we can make `Arc`s (and soon will be able to clone and destroy them correctly), but how do we get to the data inside? What we need now is an implementation of `Deref`. We'll need to import the trait: ```rust,ignore use std::ops::Deref; ``` And here's the implementation: ```rust,ignore impl Deref for Arc { type Target = T; fn deref(&self) -> &T { let inner = unsafe { self.ptr.as_ref() }; &inner.data } } ``` Pretty simple, eh? This simply dereferences the `NonNull` pointer to the `ArcInner`, then gets a reference to the data inside. ## Code Here's all the code from this section: ```rust,ignore use std::ops::Deref; impl Arc { pub fn new(data: T) -> Arc { // We start the reference count at 1, as that first reference is the // current pointer. let boxed = Box::new(ArcInner { rc: AtomicUsize::new(1), data, }); Arc { // It is okay to call `.unwrap()` here as we get a pointer from // `Box::into_raw` which is guaranteed to not be null. ptr: NonNull::new(Box::into_raw(boxed)).unwrap(), phantom: PhantomData, } } } unsafe impl Send for Arc {} unsafe impl Sync for Arc {} impl Deref for Arc { type Target = T; fn deref(&self) -> &T { let inner = unsafe { self.ptr.as_ref() }; &inner.data } } ```