diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-01-11 10:38:25 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-01-11 10:38:25 +0100 |
| commit | 877fc0321a0a6a56f38bdbe3ce03b77b44ab8316 (patch) | |
| tree | effea24198d86714b3f99af7fc1d009f17aafb54 | |
| parent | 60df9e0d38994509a595710a52d71baab1d7c28c (diff) | |
WakerRegistration: Wake previous task if any
| -rw-r--r-- | embassy/src/util/waker.rs | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/embassy/src/util/waker.rs b/embassy/src/util/waker.rs index 9735438b5..83fd8b4ff 100644 --- a/embassy/src/util/waker.rs +++ b/embassy/src/util/waker.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | use core::mem; | ||
| 1 | use core::task::Context; | 2 | use core::task::Context; |
| 2 | use core::task::Waker; | 3 | use core::task::Waker; |
| 3 | 4 | ||
| @@ -19,11 +20,21 @@ impl WakerRegistration { | |||
| 19 | // keep the old waker, skipping the clone. (In most executor implementations, | 20 | // keep the old waker, skipping the clone. (In most executor implementations, |
| 20 | // cloning a waker is somewhat expensive, comparable to cloning an Arc). | 21 | // cloning a waker is somewhat expensive, comparable to cloning an Arc). |
| 21 | Some(ref w2) if (w2.will_wake(w)) => {} | 22 | Some(ref w2) if (w2.will_wake(w)) => {} |
| 22 | // In all other cases | 23 | _ => { |
| 23 | // - we have no waker registered | 24 | // clone the new waker and store it |
| 24 | // - we have a waker registered but it's for a different task. | 25 | if let Some(old_waker) = mem::replace(&mut self.waker, Some(w.clone())) { |
| 25 | // then clone the new waker and store it | 26 | // We had a waker registered for another task. Wake it, so the other task can |
| 26 | _ => self.waker = Some(w.clone()), | 27 | // reregister itself if it's still interested. |
| 28 | // | ||
| 29 | // If two tasks are waiting on the same thing concurrently, this will cause them | ||
| 30 | // to wake each other in a loop fighting over this WakerRegistration. This wastes | ||
| 31 | // CPU but things will still work. | ||
| 32 | // | ||
| 33 | // If the user wants to have two tasks waiting on the same thing they should use | ||
| 34 | // a more appropriate primitive that can store multiple wakers. | ||
| 35 | old_waker.wake() | ||
| 36 | } | ||
| 37 | } | ||
| 27 | } | 38 | } |
| 28 | } | 39 | } |
| 29 | 40 | ||
| @@ -35,4 +46,4 @@ impl WakerRegistration { | |||
| 35 | pub fn context(&self) -> Option<Context<'_>> { | 46 | pub fn context(&self) -> Option<Context<'_>> { |
| 36 | self.waker.as_ref().map(|w| Context::from_waker(w)) | 47 | self.waker.as_ref().map(|w| Context::from_waker(w)) |
| 37 | } | 48 | } |
| 38 | } \ No newline at end of file | 49 | } |
