use std::sync::{Arc, Weak};
use crate::debug::pretty_type_name;
#[derive(Debug)]
pub struct UniqueArc<T: ?Sized>(Arc<T>);
impl<T> UniqueArc<T> {
pub fn new(value: T) -> Self {
Self(Arc::new(value))
}
pub fn into_inner(self) -> T {
Arc::into_inner(self.0).unwrap_or_else(|| {
let t_name = pretty_type_name::<T>();
panic!("UniqueArc<{t_name}> has multiple references")
})
}
pub fn weak_ref(&self) -> WeakRef<T> {
WeakRef(Arc::downgrade(&self.0))
}
}
#[derive(Debug)]
pub struct WeakRef<T: ?Sized>(Weak<T>);
impl<T> WeakRef<T> {
pub fn try_with_inner<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T) -> R,
{
self.0.upgrade().map(|arc| f(&*arc))
}
pub fn with_inner<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
self.try_with_inner(f).unwrap_or_else(|| {
let t_name = pretty_type_name::<T>();
panic!(
"UniqueArc<{t_name}> is already dropped. You can't access it by this WeakRef<{t_name}>",
)
})
}
}
impl<T> Clone for WeakRef<T> {
fn clone(&self) -> Self {
Self(Weak::clone(&self.0))
}
}