aboutsummaryrefslogtreecommitdiff
path: root/rtic-channel/src
diff options
context:
space:
mode:
authorGravatar Emil Fresk <emil.fresk@gmail.com> 2023-02-18 09:43:06 +0100
committerGravatar Henrik Tjäder <henrik@tjaders.com> 2023-03-01 00:35:20 +0100
commit1cda61fbda205920517f7b63af90c97c38ff9af6 (patch)
treece3921072005300ab089c72deaae41dc0cf3a61b /rtic-channel/src
parent002d0b0d1685473f0f81cd17346d119fc671ad9c (diff)
downloadrtic-1cda61fbda205920517f7b63af90c97c38ff9af6.tar.gz
rtic-1cda61fbda205920517f7b63af90c97c38ff9af6.tar.zst
rtic-1cda61fbda205920517f7b63af90c97c38ff9af6.zip
Make some linked list operations unsafe, and document their safety at usage
Diffstat (limited to 'rtic-channel/src')
-rw-r--r--rtic-channel/src/lib.rs15
1 files changed, 9 insertions, 6 deletions
diff --git a/rtic-channel/src/lib.rs b/rtic-channel/src/lib.rs
index 47e4a77d..a4e49358 100644
--- a/rtic-channel/src/lib.rs
+++ b/rtic-channel/src/lib.rs
@@ -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;
}