1 unstable release
0.1.0 | Feb 28, 2021 |
---|
#49 in #dynamically
115KB
1K
SLoC
exit-stack
Dynamically pin values to the stack.
lib.rs
:
Dynamically pin values to the stack.
This is motivated by a short-coming of pinning in situations where no global allocator is
available (or the use of one is not desired). The usual solution for pinning a value to the
stack is by utilizing the pin_utils
macro, which works by shadowing a value and thus making
it impossible to avoid its Drop impl being run. However, by design this can only work if the
number of values is statically known.
This crate complements the mechanism. It leverages a pinned wrapper around an area of memory to
constructs a linked list of values that are dropped together with that region, and thus can be
treated as pinned as well. The downside of this is a more imprecise tracking which requires the
values themselves to live for the 'static
lifetime by default.
Usage
Use this to have subroutines that starts some task that must be pinned while it is running. An example for this is a DMA transfer, that absolutely must signal or wait for the remote end when it is dropped (as otherwise some memory might get corrupted later). This would usually not be easily possible as stack-pinning the tasks within the subroutine would immediately drop them on exit.
use core::pin::Pin;
use exit_stack::ExitStack;
#[derive(Default)]
struct DmaTask {
// ..
}
impl DmaTask {
// Start a DMA transfer, return an identifier for it.
pub fn start(self: Pin<&mut Self>) -> usize {
// ..
}
}
fn start_pinned(mut stack: Pin<&ExitStack<DmaTask>>) -> Option<usize> {
let task = stack
.slot()?
.pin(DmaTask::default());
Some(task.start())
}