use core::fmt;
use core::mem;
use scopeguard::defer;
use super::deferred::Deferred;
use super::internal::Local;
use super::RawShared;
pub struct Guard {
pub(crate) local: *const Local,
}
impl Guard {
pub(crate) unsafe fn defer_unchecked<F, R>(&self, f: F)
where
F: FnOnce() -> R,
{
if let Some(local) = self.local.as_ref() {
local.defer(Deferred::new(move || drop(f())), self);
} else {
drop(f());
}
}
pub(crate) unsafe fn defer_destroy<T>(&self, ptr: RawShared<T>) {
self.defer_unchecked(move || unsafe { ptr.drop() });
}
pub fn flush(&self) {
if let Some(local) = unsafe { self.local.as_ref() } {
local.flush(self);
}
}
pub fn reactivate(&mut self) {
if let Some(local) = unsafe { self.local.as_ref() } {
local.repin();
}
}
pub fn reactivate_after<F, R>(&mut self, f: F) -> R
where
F: FnOnce() -> R,
{
if let Some(local) = unsafe { self.local.as_ref() } {
local.acquire_handle();
local.unpin();
}
defer! {
if let Some(local) = unsafe { self.local.as_ref() } {
mem::forget(local.pin());
local.release_handle();
}
}
f()
}
pub(crate) fn incr_manual_collection(&self) {
if let Some(local) = unsafe { self.local.as_ref() } {
local.incr_manual_collection(self);
}
}
}
impl Drop for Guard {
#[inline]
fn drop(&mut self) {
if let Some(local) = unsafe { self.local.as_ref() } {
local.unpin();
}
}
}
impl fmt::Debug for Guard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Guard { .. }")
}
}
#[inline]
pub unsafe fn unprotected() -> Guard {
Guard {
local: core::ptr::null(),
}
}