Don't leak the function that is called on drop

This commit is contained in:
Maybe Waffle 2023-05-23 14:53:36 +00:00
parent f3d597b31c
commit e2b953063d
5 changed files with 21 additions and 15 deletions

View file

@ -102,21 +102,27 @@ pub mod unord;
pub use ena::undo_log;
pub use ena::unify;
pub struct OnDrop<F: Fn()>(pub F);
/// Returns a structure that calls `f` when dropped.
pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
OnDrop(Some(f))
}
impl<F: Fn()> OnDrop<F> {
/// Forgets the function which prevents it from running.
/// Ensure that the function owns no memory, otherwise it will be leaked.
pub struct OnDrop<F: FnOnce()>(Option<F>);
impl<F: FnOnce()> OnDrop<F> {
/// Disables on-drop call.
#[inline]
pub fn disable(self) {
std::mem::forget(self);
pub fn disable(mut self) {
self.0.take();
}
}
impl<F: Fn()> Drop for OnDrop<F> {
impl<F: FnOnce()> Drop for OnDrop<F> {
#[inline]
fn drop(&mut self) {
(self.0)();
if let Some(f) = self.0.take() {
f();
}
}
}

View file

@ -7,8 +7,8 @@ use std::{
};
use crate::{
defer,
owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
OnDrop,
};
#[test]
@ -66,7 +66,7 @@ fn boxed() {
fn drop_drops() {
let flag = Arc::new(AtomicBool::new(false));
let flag_prime = Arc::clone(&flag);
let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
let d = defer(move || flag_prime.store(true, atomic::Ordering::Relaxed));
let slice = slice_owned(d, |_| &[]);