Skip to main content

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}