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

@ -240,7 +240,8 @@ impl<'a, T, const N: usize> Sender<'a, T, N> {
pub async fn send(&mut self, val: T) -> Result<(), NoReceiver<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();
@ -276,11 +277,13 @@ impl<'a, T, const N: usize> Sender<'a, T, N> {
// 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.0
.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.0.wait_queue.push(Pin::new_unchecked(link_ref)) };
return None;
}