use std::{
mem::ManuallyDrop,
ops::{Deref, DerefMut},
sync::{
mpsc::{channel, Sender},
Mutex, Once,
},
thread::spawn,
};
type Trash = Box<dyn Send>;
type TrashSender = Sender<Trash>;
pub fn adrop<T: Send + 'static>(trash: T) {
static mut TX: Option<Mutex<TrashSender>> = None;
static TX_SET: Once = Once::new();
TX_SET.call_once(|| {
let (tx, rx) = channel();
spawn(move || loop {
let _ = rx.recv();
});
unsafe {
TX = Some(Mutex::new(tx));
}
});
unsafe {
let _ = TX.as_ref().unwrap().lock().unwrap().send(Box::new(trash));
}
}
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Adrop<T: Send + 'static> {
content: Option<ManuallyDrop<T>>,
}
impl<T: Send> Adrop<T> {
pub fn new(content: T) -> Adrop<T> {
Adrop::<T> {
content: Some(ManuallyDrop::new(content)),
}
}
pub fn into_inner(mut self) -> T {
let content = unsafe { ManuallyDrop::take(self.content.as_mut().unwrap()) };
self.content = None;
content
}
}
impl<T: Send> Deref for Adrop<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.content.as_ref().unwrap()
}
}
impl<T: Send> DerefMut for Adrop<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.content.as_mut().unwrap()
}
}
impl<T: Send> Drop for Adrop<T> {
fn drop(&mut self) {
if let Some(content) = self.content.as_mut() {
unsafe {
adrop(ManuallyDrop::take(content));
}
}
}
}