Make some linked list operations unsafe, and document their safety at usage

This commit is contained in:
Emil Fresk 2023-02-18 09:43:06 +01:00 committed by Henrik Tjäder
parent 002d0b0d16
commit 1cda61fbda
6 changed files with 66 additions and 40 deletions

View file

@ -54,7 +54,8 @@ impl<T> Arbiter<T> {
pub async fn access(&self) -> ExclusiveAccess<'_, T> {
let mut link_ptr: Option<Link<Waker>> = None;
// Make this future `Drop`-safe, also shadow the original definition so we can't abuse it.
// Make this future `Drop`-safe.
// SAFETY(link_ptr): Shadow the original definition of `link_ptr` so we can't abuse it.
let mut link_ptr = LinkPtr(&mut link_ptr as *mut Option<Link<Waker>>);
let mut link_ptr2 = link_ptr.clone();
@ -89,10 +90,13 @@ impl<T> Arbiter<T> {
// Place the link in the wait queue on first run.
let link_ref = link.insert(Link::new(cx.waker().clone()));
// SAFETY: The address to the link is stable as it is hidden behind
// `link_ptr`, and `link_ptr` shadows the original making it unmovable.
self.wait_queue
.push(unsafe { Pin::new_unchecked(link_ref) });
// SAFETY(new_unchecked): The address to the link is stable as it is defined
// outside this stack frame.
// SAFETY(push): `link_ref` lifetime comes from `link_ptr` that is shadowed,
// and we make sure in `dropper` that the link is removed from the queue
// before dropping `link_ptr` AND `dropper` makes sure that the shadowed
// `link_ptr` lives until the end of the stack frame.
unsafe { self.wait_queue.push(Pin::new_unchecked(link_ref)) };
}
Poll::Pending