Skip to content

Commit 7f2f384

Browse files
y86-devfbq
authored andcommitted
rust: kernel: add drop_contents to BoxExt
Sometimes (see [1]) it is necessary to drop the value inside of a `Box<T>`, but retain the allocation. For example to reuse the allocation in the future. Introduce a new function `drop_contents` that turns a `Box<T>` into `Box<MaybeUninit<T>>` by dropping the value. Signed-off-by: Benno Lossin <[email protected]> Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [1] Reviewed-by: Boqun Feng <[email protected]> Link: https://lore.kernel.org/r/[email protected] [boqun: apply some fixes on the Example]
1 parent c1831bf commit 7f2f384

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

rust/kernel/alloc/box_ext.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use super::{AllocError, Flags};
66
use alloc::boxed::Box;
77
use core::mem::MaybeUninit;
8+
use core::ptr;
89

910
/// Extensions to [`Box`].
1011
pub trait BoxExt<T>: Sized {
@@ -17,6 +18,22 @@ pub trait BoxExt<T>: Sized {
1718
///
1819
/// The allocation may fail, in which case an error is returned.
1920
fn new_uninit(flags: Flags) -> Result<Box<MaybeUninit<T>>, AllocError>;
21+
22+
/// Drops the contents, but keeps the allocation.
23+
///
24+
/// # Examples
25+
///
26+
/// ```
27+
/// use kernel::alloc::{flags, box_ext::BoxExt};
28+
///
29+
/// let value = Box::new([0; 32], flags::GFP_KERNEL)?;
30+
/// let value = value.drop_contents();
31+
/// // Now we can re-use `value`:
32+
/// Box::write(value, [1; 32]);
33+
///
34+
/// # Ok::<(), Error>(())
35+
/// ```
36+
fn drop_contents(self) -> Box<MaybeUninit<T>>;
2037
}
2138

2239
impl<T> BoxExt<T> for Box<T> {
@@ -53,4 +70,12 @@ impl<T> BoxExt<T> for Box<T> {
5370
// zero-sized types, we use `NonNull::dangling`.
5471
Ok(unsafe { Box::from_raw(ptr) })
5572
}
73+
74+
fn drop_contents(self) -> Box<MaybeUninit<T>> {
75+
let ptr = Box::into_raw(self);
76+
// SAFETY: `ptr` is valid, because it came from `Box::into_raw`.
77+
unsafe { ptr::drop_in_place(ptr) };
78+
// SAFETY: `ptr` is valid, because it came from `Box::into_raw`.
79+
unsafe { Box::from_raw(ptr.cast()) }
80+
}
5681
}

0 commit comments

Comments
 (0)