Skip to content

Commit 5b77eae

Browse files
committed
Add DropGuard convenience wrapper
This provides a convenient RAII-style way to ensure that a function is always called when a specific value gets dropped.
1 parent 09c584a commit 5b77eae

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

rclrs/src/drop_guard.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::{
2+
mem::ManuallyDrop,
3+
ops::{Deref, DerefMut, Drop, Fn},
4+
};
5+
6+
/// A wrapper providing additional drop-logic for the contained value.
7+
///
8+
/// When this wrapper is dropped, the contained value will be passed into the given function before
9+
/// being destructed.
10+
pub(crate) struct DropGuard<T, F: Fn(T)> {
11+
value: ManuallyDrop<T>,
12+
drop_fn: F,
13+
}
14+
15+
impl<T, F: Fn(T)> DropGuard<T, F> {
16+
/// Create a new `DropGuard` with the given value and drop function.
17+
pub fn new(value: T, drop_fn: F) -> Self {
18+
Self {
19+
value: ManuallyDrop::new(value),
20+
drop_fn,
21+
}
22+
}
23+
}
24+
25+
impl<T, F: Fn(T)> Deref for DropGuard<T, F> {
26+
type Target = T;
27+
28+
fn deref(&self) -> &T {
29+
&*self.value
30+
}
31+
}
32+
33+
impl<T, F: Fn(T)> DerefMut for DropGuard<T, F> {
34+
fn deref_mut(&mut self) -> &mut T {
35+
&mut *self.value
36+
}
37+
}
38+
39+
impl<T, F: Fn(T)> Drop for DropGuard<T, F> {
40+
fn drop(&mut self) {
41+
// SAFETY: ManuallyDrop::take() leaves `self.value` in an uninitialized state, meaning that
42+
// it must not be accessed further. This is guaranteed since `self` is being dropped and
43+
// cannot be accessed after this function completes. Moreover, the strict ownership of
44+
// `self.value` means that it cannot be accessed by `self.drop_fn`'s drop function either.
45+
let value = unsafe { ManuallyDrop::take(&mut self.value) };
46+
(self.drop_fn)(value);
47+
}
48+
}

rclrs/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod arguments;
1010
mod client;
1111
mod clock;
1212
mod context;
13+
mod drop_guard;
1314
mod error;
1415
mod executor;
1516
mod node;
@@ -38,6 +39,7 @@ pub use arguments::*;
3839
pub use client::*;
3940
pub use clock::*;
4041
pub use context::*;
42+
use drop_guard::DropGuard;
4143
pub use error::*;
4244
pub use executor::*;
4345
pub use node::*;

0 commit comments

Comments
 (0)