use super::Inner;
use std::{panic::Location, sync::Arc, time::Duration};
#[cfg(not(miri))]
use std::time::Instant;
#[derive(Debug)]
pub(crate) struct GuardInfo {
location: &'static Location<'static>,
#[cfg(not(miri))]
created_at: Instant,
}
impl GuardInfo {
pub(crate) fn new(location: &'static Location<'static>) -> Arc<Self> {
Arc::new(Self {
location,
#[cfg(not(miri))]
created_at: Instant::now(),
})
}
pub(crate) fn location(&self) -> &'static Location<'static> {
self.location
}
#[allow(clippy::unnecessary_wraps)] pub(crate) fn age(&self) -> Option<Duration> {
#[cfg(not(miri))]
{
Some(self.created_at.elapsed())
}
#[cfg(miri)]
{
None
}
}
}
#[derive(Debug)]
pub struct Guard {
inner: Arc<Inner>,
info: Arc<GuardInfo>,
}
impl Guard {
#[track_caller]
pub(crate) fn new(inner: &Arc<Inner>) -> Self {
Self::at_location(inner, Location::caller())
}
fn at_location(inner: &Arc<Inner>, location: &'static Location<'static>) -> Self {
let info = GuardInfo::new(location);
inner.increment_guard(Arc::downgrade(&info));
Self {
inner: Arc::clone(inner),
info,
}
}
}
impl Drop for Guard {
fn drop(&mut self) {
self.inner.decrement_guard();
}
}
impl Clone for Guard {
fn clone(&self) -> Self {
Self::at_location(&self.inner, self.info.location())
}
}
impl Eq for Guard {}
impl PartialEq for Guard {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}