# Dropping

We now need a way to decrease the reference count and drop the data once it is low enough, otherwise the data will live forever on the heap.

To do this, we can implement `Drop`.

Basically, we need to:

1. Decrement the reference count
2. If there is only one reference remaining to the data, then:
3. Atomically fence the data to prevent reordering of the use and deletion of the data
4. Drop the inner data

First, we'll need to get access to the `ArcInner`:

    let inner = unsafe { self.ptr.as_ref() };

Now, we need to decrement the reference count. To streamline our code, we can also return if the returned value from `fetch_sub` (the value of the reference count before decrementing it) is not equal to `1` (which happens when we are not the last reference to the data).

    if inner.rc.fetch_sub(1, Ordering::Relaxed) != 1 {
        return;
    }

We then need to create an atomic fence to prevent reordering of the use of the data and deletion of the data. As described in the standard library's implementation of `Arc`:

> This fence is needed to prevent reordering of use of the data and deletion of the data. Because it is marked `Release`, the decreasing of the reference count synchronizes with this `Acquire` fence. This means that use of the data happens before decreasing the reference count, which happens before this fence, which happens before the deletion of the data.

> As explained in the Boost documentation,

> > It is important to enforce any possible access to the object in one thread (through an existing reference) to happen before deleting the object in a different thread. This is achieved by a "release" operation after dropping a reference (any access to the object through this reference must obviously happened before), and an "acquire" operation before deleting the object.

> In particular, while the contents of an Arc are usually immutable, it's possible to have interior writes to something like a Mutex. Since a Mutex is not acquired when it is deleted, we can't rely on its synchronization logic to make writes in thread A visible to a destructor running in thread B.

> Also note that the Acquire fence here could probably be replaced with an Acquire load, which could improve performance in highly-contended situations. See 2.

To do this, we do the following:

    atomic::fence(Ordering::Acquire);

We'll need to import `std::sync::atomic` itself:

    use std::sync::atomic;

Finally, we can drop the data itself. We use `Box::from_raw` to drop the boxed `ArcInner<T>` and its data. This takes a `*mut T` and not a `NonNull<T>`, so we must convert using `NonNull::as_ptr`.

    unsafe { Box::from_raw(self.ptr.as_ptr()); }

This is safe as we know we have the last pointer to the `ArcInner` and that its pointer is valid.

Now, let's wrap this all up inside the `Drop` implementation:

    impl<T> Drop for Arc<T> {
        fn drop(&mut self) {
            let inner = unsafe { self.ptr.as_ref() };
            if inner.rc.fetch_sub(1, Ordering::Release) != 1 {
                return;
            }
            // This fence is needed to prevent reordering of the use and deletion
            // of the data.
            atomic::fence(Ordering::Acquire);
            // This is safe as we know we have the last pointer to the `ArcInner`
            // and that its pointer is valid.
            unsafe { Box::from_raw(self.ptr.as_ptr()); }
        }
    }