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}