use std::cell::RefCell;
use std::rc::Rc;
type Cleanups = Rc<RefCell<Vec<Box<dyn FnOnce()>>>>;
pub struct Tracker {
cleanups: Cleanups,
}
impl Tracker {
pub(super) fn new() -> Self {
Self {
cleanups: Rc::new(RefCell::new(Vec::new())),
}
}
pub(crate) fn add<F: FnOnce() + 'static>(&self, cleanup: F) {
self.cleanups.borrow_mut().push(Box::new(cleanup));
}
pub fn subscription_count(&self) -> usize {
self.cleanups.borrow().len()
}
}
impl Drop for Tracker {
fn drop(&mut self) {
if let Ok(mut cleanups) = self.cleanups.try_borrow_mut() {
for cleanup in cleanups.drain(..) {
cleanup();
}
}
}
}
impl Clone for Tracker {
fn clone(&self) -> Self {
Self {
cleanups: self.cleanups.clone(),
}
}
}
pub struct DisposableTracker {
tracker: Tracker,
}
impl DisposableTracker {
pub fn new() -> Self {
Self {
tracker: Tracker::new(),
}
}
pub fn tracker(&self) -> &Tracker {
&self.tracker
}
pub fn dispose(&mut self) {
if let Ok(mut cleanups) = self.tracker.cleanups.try_borrow_mut() {
for cleanup in cleanups.drain(..) {
cleanup();
}
}
}
pub fn subscription_count(&self) -> usize {
self.tracker.subscription_count()
}
}
impl Default for DisposableTracker {
fn default() -> Self {
Self::new()
}
}