use crate::deferred_panics_helper::IDropHandler;
use crate::{debug_println, IMetadata, ItemHolder};
use core::any::Any;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
pub(crate) struct DropHandler<T: ?Sized> {
panic: Option<alloc::boxed::Box<dyn Any + Send + 'static>>,
phantom: PhantomData<*mut T>,
}
impl<T: ?Sized> Default for DropHandler<T> {
fn default() -> Self {
Self {
panic: None,
phantom: Default::default(),
}
}
}
impl<T: ?Sized, M: IMetadata> IDropHandler<T, M> for DropHandler<T> {
fn do_drop(&mut self, item_ptr: *mut ItemHolder<T, M>) {
self.run(|| {
let payload = unsafe { &(*item_ptr).payload };
debug_println!("payload ref created (std drop)");
unsafe { ManuallyDrop::drop(&mut *payload.get()) };
debug_println!("payload dropped");
})
}
fn report_sole_user(&mut self) {}
}
impl<T: ?Sized> DropHandler<T> {
pub(crate) fn do_drop_value(&mut self, value: T)
where
T: Sized,
{
self.run(move || {
let _ = value;
});
}
pub(crate) fn run(&mut self, job: impl FnOnce()) {
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(job)) {
Ok(()) => {}
Err(err) => {
self.panic.get_or_insert(err);
}
}
}
pub(crate) fn resume_any_panics(self) {
if let Some(panic) = self.panic {
std::panic::resume_unwind(panic);
}
}
}