fbl/recyclable.rs
1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7use core::ffi::c_void;
8use core::ptr::NonNull;
9use kalloc::AllocError;
10
11/// Trait for types that can be recycled (deallocated).
12///
13/// # Safety
14///
15/// Implementing this trait is unsafe because the implementer must ensure that:
16/// - `allocate` returns a valid pointer that can be safely deallocated by `recycle`.
17/// - `recycle` correctly deallocates the pointer and does not cause double-free or use-after-free.
18pub unsafe trait Recyclable: Sized {
19 /// Allocates a new instance of `Self`.
20 fn allocate(value: Self) -> Result<NonNull<Self>, AllocError>;
21
22 /// Recycles the object.
23 ///
24 /// # Safety
25 ///
26 /// - The caller must ensure that `ptr` points to a valid, fully-initialized
27 /// instance of `Self` that has no other references.
28 /// - The caller must not use the pointer or any references derived from it
29 /// after this call.
30 unsafe fn recycle(ptr: NonNull<Self>);
31
32 /// Helper for FFI functions to call `recycle`.
33 ///
34 /// # Safety
35 ///
36 /// - The caller must ensure that `ptr` is valid and points to a valid object
37 /// of type `Self` that has no other references.
38 /// - The caller must not use the pointer or any references derived from it
39 /// after this call.
40 unsafe fn recycle_ffi(ptr: *mut c_void) {
41 // SAFETY: The caller of `recycle_ffi` must ensure that `ptr` is non-null
42 // and points to a valid `Self` that can be safely recycled.
43 unsafe {
44 Self::recycle(NonNull::new_unchecked(ptr as *mut Self));
45 }
46 }
47}
48
49/// Trait for types that can be allocated in an uninitialized state.
50///
51/// # Safety
52///
53/// Implementing this trait is unsafe because the implementer must ensure that:
54/// - `allocate_uninit` returns a valid pointer to uninitialized memory that can
55/// be safely deallocated by `recycle_uninit`.
56/// - `recycle_uninit` correctly deallocates the pointer without dropping the content
57/// (as it is uninitialized) and does not cause double-free or use-after-free.
58pub unsafe trait UninitRecyclable: Recyclable {
59 /// Allocates a new uninitialized instance of `Self`.
60 fn allocate_uninit() -> Result<NonNull<core::mem::MaybeUninit<Self>>, AllocError>;
61
62 /// Recycles an uninitialized object.
63 ///
64 /// # Safety
65 ///
66 /// - The caller must ensure that `ptr` points to a valid (but possibly uninitialized)
67 /// instance of `Self` that has no other references.
68 /// - The caller must not use the pointer or any references derived from it
69 /// after this call.
70 unsafe fn recycle_uninit(ptr: NonNull<core::mem::MaybeUninit<Self>>);
71}