#[cfg(doc)]
use std::sync::Arc;
use {
crate::{Lock, lock::Guard},
debug_fn::debug_fn,
opera::PhantomNotSync,
static_assertions::{assert_impl_all, assert_not_impl_any},
std::{
cell::UnsafeCell,
fmt::{Debug, Formatter},
ops::Deref,
},
};
#[cfg(test)]
mod tests;
pub struct Locked<T>
where
T: ?Sized,
{
lock: Lock,
_phantom_not_sync: PhantomNotSync,
value: UnsafeCell<T>,
}
#[allow(dead_code)]
const _: () = {
fn assert_send<T: ?Sized + Send>() {}
fn assert<T: ?Sized + Send>() {
assert_send::<Locked<T>>();
}
};
assert_impl_all!(Lock: Sync);
unsafe impl<T> Sync for Locked<T> where T: ?Sized + Send {}
impl<T> Deref for Locked<T>
where
T: ?Sized,
{
type Target = Lock;
#[inline]
fn deref(&self) -> &Self::Target {
&self.lock
}
}
impl Lock {
#[inline]
pub fn wrap<T>(&self, value: T) -> Locked<T> {
Locked {
lock: self.clone(),
_phantom_not_sync: Default::default(),
value: UnsafeCell::new(value),
}
}
}
impl<T> Locked<T>
where
T: ?Sized,
{
#[inline]
pub fn get<'a>(&'a self, guard: &'a Guard) -> &'a T {
assert_not_impl_any!(Guard<'_>: Sync, Send);
assert!(
self.lock.is_locked_by(guard),
"guard does not guard this object",
);
unsafe { &*self.value.get() }
}
#[inline]
pub fn into_inner(self) -> T
where
T: Sized,
{
self.value.into_inner()
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
#[inline]
pub fn data_ptr(&self) -> *const T {
self.value.get()
}
}
impl<T> Debug for Locked<T>
where
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Locked")
.field("lock_id", &self.lock.addr())
.field(
"value",
&debug_fn(|fmt| {
if let Some(guard) = self.lock.try_lock() {
Debug::fmt(self.get(&guard), fmt)
} else {
fmt.write_str("<locked>")
}
}),
)
.finish_non_exhaustive()
}
}