228 lines
5.6 KiB
Rust
228 lines
5.6 KiB
Rust
//! A helper type for Arc<Mutex<T>>
|
|
//! Currently there are mut versions (of Ref stuff) which don't do anything different under the hood,
|
|
//! leaving them in for now in case I decide RwLock is a desired feature
|
|
|
|
use std::{
|
|
marker::Unsize,
|
|
ops::{CoerceUnsized, Deref, DerefMut},
|
|
sync::{Arc, MappedMutexGuard, Mutex, MutexGuard, Weak},
|
|
};
|
|
|
|
pub struct Handle<T: ?Sized>(Arc<Mutex<T>>);
|
|
pub struct WeakHandle<T: ?Sized>(Weak<Mutex<T>>);
|
|
|
|
pub type Ref<'a, T> = MutexGuard<'a, T>;
|
|
pub type RefMut<'a, T> = MutexGuard<'a, T>;
|
|
|
|
pub type RefMap<'a, T> = MappedMutexGuard<'a, T>;
|
|
pub type RefMapMut<'a, T> = MappedMutexGuard<'a, T>;
|
|
|
|
impl<T: ?Sized> Handle<T> {
|
|
pub fn get(&self) -> Ref<'_, T> {
|
|
self.0.lock().unwrap()
|
|
}
|
|
|
|
pub fn get_mut(&self) -> RefMut<'_, T> {
|
|
self.0.lock().unwrap()
|
|
}
|
|
|
|
pub fn get_take<'a>(self) -> RefGuard<'a, T> {
|
|
let handle = self;
|
|
RefGuard {
|
|
guard: unsafe {
|
|
std::mem::transmute::<MutexGuard<'_, T>, MutexGuard<'_, T>>(
|
|
handle.0.lock().unwrap(),
|
|
)
|
|
},
|
|
handle,
|
|
}
|
|
}
|
|
|
|
pub fn get_take_mut<'a>(self) -> RefGuardMut<'a, T> {
|
|
let handle = self;
|
|
RefGuardMut {
|
|
guard: unsafe {
|
|
std::mem::transmute::<MutexGuard<'_, T>, MutexGuard<'_, T>>(
|
|
handle.0.lock().unwrap(),
|
|
)
|
|
},
|
|
handle,
|
|
}
|
|
}
|
|
|
|
pub fn refs(&self) -> usize {
|
|
Arc::strong_count(&self.0)
|
|
}
|
|
|
|
pub fn weak(&self) -> WeakHandle<T> {
|
|
WeakHandle(Arc::downgrade(&self.0))
|
|
}
|
|
|
|
/// # Safety
|
|
/// you must guarantee the type outside
|
|
/// ideally you check the typeid, but this is often used
|
|
/// when the trait object is wrapped one or more times
|
|
/// and you'd have to implement each one individually
|
|
pub unsafe fn downcast<U: 'static>(self) -> Handle<U>
|
|
where
|
|
T: 'static,
|
|
{
|
|
let raw: *const Mutex<T> = Arc::into_raw(self.0);
|
|
let raw: *const Mutex<U> = raw.cast();
|
|
Handle(unsafe { Arc::from_raw(raw) })
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> WeakHandle<T> {
|
|
pub fn strong(&self) -> Option<Handle<T>> {
|
|
Some(Handle(self.0.upgrade()?))
|
|
}
|
|
|
|
pub fn dropped(&self) -> bool {
|
|
self.0.strong_count() == 0
|
|
}
|
|
|
|
/// # Safety
|
|
/// you must guarantee the type outside
|
|
pub unsafe fn downcast<U: 'static>(self) -> WeakHandle<U>
|
|
where
|
|
T: 'static,
|
|
{
|
|
let raw: *const Mutex<T> = self.0.into_raw();
|
|
let raw: *const Mutex<U> = raw.cast();
|
|
WeakHandle(unsafe { Weak::from_raw(raw) })
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Clone for Handle<T> {
|
|
fn clone(&self) -> Self {
|
|
Self(self.0.clone())
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Clone for WeakHandle<T> {
|
|
fn clone(&self) -> Self {
|
|
Self(self.0.clone())
|
|
}
|
|
}
|
|
|
|
impl<T: Default> Default for Handle<T> {
|
|
fn default() -> Self {
|
|
Self(Default::default())
|
|
}
|
|
}
|
|
|
|
impl<T> From<T> for Handle<T> {
|
|
fn from(value: T) -> Self {
|
|
Self(Arc::new(Mutex::new(value)))
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Handle<U>> for Handle<T> {}
|
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<WeakHandle<U>> for WeakHandle<T> {}
|
|
|
|
// yucky
|
|
|
|
// TODO: is drop order important here?
|
|
// something stupid could happen that I don't know about
|
|
// if handle is dropped before guard
|
|
pub struct RefGuard<'a, T: ?Sized> {
|
|
guard: MutexGuard<'a, T>,
|
|
handle: Handle<T>,
|
|
}
|
|
|
|
pub struct RefGuardMut<'a, T: ?Sized> {
|
|
guard: MutexGuard<'a, T>,
|
|
handle: Handle<T>,
|
|
}
|
|
|
|
pub struct MappedRefGuard<'a, T: ?Sized, U> {
|
|
guard: MappedMutexGuard<'a, U>,
|
|
handle: Handle<T>,
|
|
}
|
|
|
|
pub struct MappedRefGuardMut<'a, T: ?Sized, U> {
|
|
guard: MappedMutexGuard<'a, U>,
|
|
handle: Handle<T>,
|
|
}
|
|
|
|
impl<'a, T: ?Sized> RefGuard<'a, T> {
|
|
pub fn map<U>(s: Self, f: impl FnOnce(&mut T) -> &mut U) -> MappedRefGuard<'a, T, U> {
|
|
MappedRefGuard {
|
|
guard: MutexGuard::map(s.guard, f),
|
|
handle: s.handle,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, T: ?Sized> RefGuardMut<'a, T> {
|
|
pub fn map<U>(s: Self, f: impl FnOnce(&mut T) -> &mut U) -> MappedRefGuardMut<'a, T, U> {
|
|
MappedRefGuardMut {
|
|
guard: MutexGuard::map(s.guard, f),
|
|
handle: s.handle,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, T: ?Sized, U> MappedRefGuard<'a, T, U> {
|
|
pub fn map<U2>(s: Self, f: impl FnOnce(&mut U) -> &mut U2) -> MappedRefGuard<'a, T, U2> {
|
|
MappedRefGuard {
|
|
guard: MappedMutexGuard::map(s.guard, f),
|
|
handle: s.handle,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, T: ?Sized, U> MappedRefGuardMut<'a, T, U> {
|
|
pub fn map<U2>(s: Self, f: impl FnOnce(&mut U) -> &mut U2) -> MappedRefGuardMut<'a, T, U2> {
|
|
MappedRefGuardMut {
|
|
guard: MappedMutexGuard::map(s.guard, f),
|
|
handle: s.handle,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Deref for RefGuard<'_, T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.guard
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Deref for RefGuardMut<'_, T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.guard
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> DerefMut for RefGuardMut<'_, T> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.guard
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized, U> Deref for MappedRefGuard<'_, T, U> {
|
|
type Target = U;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.guard
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized, U> Deref for MappedRefGuardMut<'_, T, U> {
|
|
type Target = U;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.guard
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized, U> DerefMut for MappedRefGuardMut<'_, T, U> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.guard
|
|
}
|
|
}
|