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:
- Get the
ArcInner
value of theArc
- Increment the atomic reference count
- 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,
}
}
}