use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Condvar, Mutex};
use crate::blocking_cell::ThreadTracker;
use crate::guards::{MutGuard, RefGuard};
use crate::panicking::InaccessibleGuard;
#[derive(Debug)]
pub struct RefGuardBlocking<'a, T> {
inner: ManuallyDrop<RefGuard<'a, T>>,
mut_condition: Arc<Condvar>,
state: Arc<Mutex<ThreadTracker>>,
}
impl<'a, T> RefGuardBlocking<'a, T> {
pub(crate) fn new(
inner: RefGuard<'a, T>,
mut_condition: Arc<Condvar>,
state: Arc<Mutex<ThreadTracker>>,
) -> Self {
Self {
inner: ManuallyDrop::new(inner),
mut_condition,
state,
}
}
}
impl<'a, T> Deref for RefGuardBlocking<'a, T> {
type Target = <RefGuard<'a, T> as Deref>::Target;
fn deref(&self) -> &Self::Target {
self.inner.deref().deref()
}
}
impl<T> Drop for RefGuardBlocking<'_, T> {
fn drop(&mut self) {
let mut state_lock = self.state.lock().unwrap();
state_lock.decrement_current_thread_shared_count();
unsafe { ManuallyDrop::drop(&mut self.inner) };
self.mut_condition.notify_one();
drop(state_lock);
}
}
#[derive(Debug)]
pub struct MutGuardBlocking<'a, T> {
inner: ManuallyDrop<MutGuard<'a, T>>,
mut_condition: Arc<Condvar>,
immut_condition: Arc<Condvar>,
state: Arc<Mutex<ThreadTracker>>,
}
impl<'a, T> MutGuardBlocking<'a, T> {
pub(crate) fn new(
inner: MutGuard<'a, T>,
mut_condition: Arc<Condvar>,
immut_condition: Arc<Condvar>,
state: Arc<Mutex<ThreadTracker>>,
) -> Self {
Self {
inner: ManuallyDrop::new(inner),
immut_condition,
mut_condition,
state,
}
}
}
impl<'a, T> Deref for MutGuardBlocking<'a, T> {
type Target = <MutGuard<'a, T> as Deref>::Target;
fn deref(&self) -> &Self::Target {
let _tracker_guard = self.state.lock().unwrap();
self.inner.deref().deref()
}
}
impl<T> DerefMut for MutGuardBlocking<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
let _tracker_guard = self.state.lock().unwrap();
self.inner.deref_mut().deref_mut()
}
}
impl<T> Drop for MutGuardBlocking<'_, T> {
fn drop(&mut self) {
let _tracker_guard = self.state.lock().unwrap();
unsafe { ManuallyDrop::drop(&mut self.inner) };
self.mut_condition.notify_one();
self.immut_condition.notify_all();
}
}
#[derive(Debug)]
pub struct InaccessibleGuardBlocking<'a, T> {
inner: ManuallyDrop<InaccessibleGuard<'a, T>>,
state: Arc<Mutex<ThreadTracker>>,
}
impl<'a, T> InaccessibleGuardBlocking<'a, T> {
pub(crate) fn new(inner: InaccessibleGuard<'a, T>, state: Arc<Mutex<ThreadTracker>>) -> Self {
Self {
inner: ManuallyDrop::new(inner),
state,
}
}
pub fn try_drop(self) -> Result<(), Self> {
let can_drop = {
let _tracker_guard = self.state.lock();
self.inner.can_drop()
};
if !can_drop { Err(self) } else { Ok(()) }
}
}
impl<T> Drop for InaccessibleGuardBlocking<'_, T> {
fn drop(&mut self) {
let _tracker_guard = self.state.lock().unwrap();
unsafe { ManuallyDrop::drop(&mut self.inner) };
drop(_tracker_guard)
}
}