I have a use case where a value is shared by multiple reference-counting pointers, but only one specific pointer (the owner) will actually use the value, and the other pointers (the holders) can only access the value on destruction. Here is what I come up with (playground link):
pub mod owner_and_holder {
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
/// A reference-counting pointer to a `T` object, but cannot access it until destruction.
pub struct Holder<T>
where
T: ?Sized,
{
inner: Arc<T>,
}
impl<T> Clone for Holder<T>
where
T: ?Sized,
{
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
// SAFETY: Sending a `Holder<T>` to another thread may causing it to destruct on that another thread, which only
// requires `T` being `Send`.
unsafe impl<T> Send for Holder<T> where T: Send + ?Sized {}
// Sharing a `Holder<T>` with another thread allows user to cloning it into that thread, which may causing it to
// destruct on that thread, which only requires `T` being `Send`.
unsafe impl<T> Sync for Holder<T> where T: Send + ?Sized {}
/// A reference-counting pointer to a `T` object, with exclusive access to it, except for destructor, which is
/// executed by the last `Owner<T>` or `Holder<T>` pointing to it.
pub struct Owner<T>
where
T: ?Sized,
{
inner: Arc<T>,
}
impl<T> Owner<T>
where
T: ?Sized,
{
pub fn new(value: T) -> Self
where
T: Sized,
{
Self {
inner: Arc::new(value),
}
}
/// Creates a `Holder<T>` pointing to the the `T` value, does not have access to `T` until destruction, and
/// extends the lifetime of `T` with it.
pub fn holder(this: &Self) -> Holder<T> {
Holder {
inner: Arc::clone(&this.inner),
}
}
}
impl<T> Deref for Owner<T>
where
T: ?Sized,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T> DerefMut for Owner<T>
where
T: ?Sized,
{
fn deref_mut(&mut self) -> &mut Self::Target {
// SAFETY: Having a `Owner<T>` means that no `Holder<T>` is the last referencing pointer, which means we
// have exclusive access to `T`.
unsafe { &mut *Arc::as_ptr(&self.inner).cast_mut() }
}
}
// SAFETY: `Owner<T>` has the same safety requirements as `T`.
unsafe impl<T> Send for Owner<T> where T: Send + ?Sized {}
// SAFETY: `Owner<T>` has the same safety requirements as `T`.
unsafe impl<T> Sync for Owner<T> where T: Sync + ?Sized {}
}
fn main() {
use owner_and_holder::Owner;
let mut owner = Owner::new(42);
let holder_1 = Owner::holder(&owner);
*owner = 43;
let holder_2 = holder_1.clone();
assert_eq!(*owner, 43);
drop(owner);
drop(holder_1);
drop(holder_2);
}
Is this implementation sound? Does this pattern have a known name?