You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nomicon/src/arc-clone.md

2.0 KiB

Cloning

Now that we've got some basic code set up, we'll need a way to clone the Arc.

Basically, we need to:

  1. Get the ArcInner value of the Arc
  2. Increment the atomic reference count
  3. Construct a new instance of the Arc from the inner pointer

Next, we can update the atomic reference count as follows:

self.inner().rc.fetch_add(1, Ordering::Relaxed);

As described in the standard library's implementation of Arc cloning:

Using a relaxed ordering is alright here, as knowledge of the original reference prevents other threads from erroneously deleting the object.

As explained in the Boost documentation:

Increasing the reference counter can always be done with memory_order_relaxed: New references to an object can only be formed from an existing reference, and passing an existing reference from one thread to another must already provide any required synchronization.

We'll need to add another import to use Ordering:

use std::sync::atomic::Ordering;

It is possible that in some contrived programs (e.g. using mem::forget) that the reference count could overflow, but it's unreasonable that would happen in any reasonable program.

Then, we need to return a new instance of the Arc:

Self {
    ptr: self.ptr,
    _marker: PhantomData
}

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

use std::sync::atomic::Ordering;

impl<T> Clone for Arc<T> {
    fn clone(&self) -> Arc<T> {
        // Using a relaxed ordering is alright here as knowledge of the original
        // reference prevents other threads from wrongly deleting the object.
        self.inner().rc.fetch_add(1, Ordering::Relaxed);
        Self {
            ptr: self.ptr,
            _marker: PhantomData,
        }
    }
}