pub struct Defer<F: FnOnce()> {
f: Option<F>,
}
impl<F: FnOnce()> Defer<F> {
pub fn new(f: F) -> Defer<F> {
Defer { f: Some(f) }
}
}
impl<F: FnOnce()> Drop for Defer<F> {
fn drop(&mut self) {
if let Some(f) = self.f.take() {
f()
}
}
}
#[cfg(feature = "async")]
mod async_defer {
use std::future::Future;
use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime;
pub struct AsyncDefer<F: Future<Output = ()> + Send + 'static> {
f: Option<F>,
rt: Runtime,
counter: Arc<Mutex<usize>>,
}
impl<F: Future<Output = ()> + Send + 'static> AsyncDefer<F> {
pub fn new(counter: usize, f: F) -> Arc<Mutex<Self>> {
let counter = Arc::new(Mutex::new(counter));
let defer = AsyncDefer {
f: Some(f),
rt: Runtime::new().unwrap(),
counter: counter.clone(),
};
Arc::new(Mutex::new(defer))
}
pub fn exec(&mut self, action: impl FnOnce() + Send + 'static) {
let counter = self.counter.lock().unwrap().clone();
self.rt.spawn(async move {
action();
let mut counter = counter.lock().unwrap();
*counter -= 1;
});
}
}
}
#[macro_export]
macro_rules! defer {
($($t:tt)*) => {
$crate::Defer::new(|| { $($t)* })
};
}
#[cfg(feature = "async")]
#[macro_export]
macro_rules! async_defer {
($count:expr, $f:expr) => {
$crate::async_defer::AsyncDefer::new($count, $f)
};
}
#[cfg(feature = "async")]
#[macro_export]
macro_rules! exec_before_defer {
($defer:expr, $action:expr) => {
$defer.lock().unwrap().exec($action)
};
}