maitake/task/
storage.rs

1use super::Task;
2use core::future::Future;
3use core::ptr::NonNull;
4
5/// A trait representing a heap allocation that can own a [`Task`].
6///
7/// This is used to contain tasks at runtime, and abstract over the
8/// type erasure and type recovery steps, e.g. converting a heap
9/// allocation type into a [`NonNull`] pointer, and recovering it
10/// back into a heap allocation from a [`NonNull`] pointer
11///
12/// This trait is exposed publicly to allow for end users to implement
13/// for their own heap allocation types, if tasks must be stored in
14/// an allocation type other than [`Box`].
15///
16/// This trait is ONLY appropriate for heap allocation types that represent
17/// exclusive ownership of the contained data, as it may be mutated while
18/// in pointer form. For example, the `Box` type would match this guarantee,
19/// but the `Arc` type would not, as it allows for shared access, and NOT
20/// exclusive mutable access.
21///
22/// **Note**: The type that implements this trait is typically NOT the heap
23/// allocation type itself, but a "Marker Type" that represents the
24/// intended storage medium. See the [`BoxStorage`] type (available with the
25/// "alloc" feature active) for an implementation example
26///
27/// [`Task`]: crate::task::Task
28/// [`Box`]: alloc::boxed::Box
29/// [`BoxStorage`]: crate::task::BoxStorage
30pub trait Storage<S, F: Future>: Sized {
31    /// The type of a stored Task.
32    ///
33    /// As the type that implements the Storage trait is a Marker Type,
34    /// This associated type is the actual heap type that will be used
35    /// to contain the Task.
36    type StoredTask;
37
38    /// Convert an owned, heap-allocated [`Task`] type to a raw pointer
39    ///
40    /// This method should produce a [`NonNull`] pointer, while not actually
41    /// dropping the contained task.
42    fn into_raw(task: Self::StoredTask) -> NonNull<Task<S, F, Self>>;
43
44    /// Convert a raw task pointer into an owned, heap`allocated [`Task`] type
45    ///
46    /// This method should produce a heap-allocated type, which can be
47    /// dropped to perform the correct destructor actions
48    fn from_raw(ptr: NonNull<Task<S, F, Self>>) -> Self::StoredTask;
49}
50
51feature! {
52    #![feature = "alloc"]
53    use alloc::boxed::Box;
54
55    /// A type representing [`Box`] storage of a task
56    ///
57    /// [`Box`]: alloc::boxed::Box
58    pub struct BoxStorage;
59
60    impl<S, F: Future> Storage<S, F> for BoxStorage {
61        type StoredTask = Box<Task<S, F, BoxStorage>>;
62
63        fn into_raw(task: Box<Task<S, F, BoxStorage>>) -> NonNull<Task<S, F, BoxStorage>> {
64            unsafe {
65                crate::util::non_null(Box::into_raw(task))
66            }
67        }
68
69        fn from_raw(ptr: NonNull<Task<S, F, BoxStorage>>) -> Box<Task<S, F, BoxStorage>> {
70            unsafe { Box::from_raw(ptr.as_ptr()) }
71        }
72    }
73
74}