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