rust / expert
Snippet
Unterbrechung asynchroner Tasks durch manuelle Waker-Aktivierung
Dieses Snippet implementiert kooperatives Multitasking, indem es eine benutzerdefinierte Future erstellt, die die Kontrolle einmal an den asynchronen Executor zurückgibt, bevor sie sich selbst aufweckt, um zu verhindern, dass ein einzelner lang laufender Task andere verhungern lässt.
snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use std::future::Future;use std::pin::Pin;use std::task::{Context, Poll};struct YieldOnce {yielded: bool,}impl Future for YieldOnce {type Output = ();fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {if self.yielded {Poll::Ready(())} else {self.yielded = true;cx.waker().wake_by_ref();Poll::Pending}}}async fn execute_cooperative_task() -> i32 {let mut sum = 0;for i in 0..10 {sum += i;if i % 3 == 0 {YieldOnce { yielded: false }.await;}}sum}
Erklärung
1
struct YieldOnce
Hält den Zustand darüber, ob die Future die Ausführung bereits an die Executor-Schleife abgegeben hat.
2
cx.waker().wake_by_ref()
Plant den aktuellen Task für die erneute Ausführung im nächsten Durchlauf des Executors ein.
3
Poll::Pending
Signalisiert dem Executor, dass der Task vorübergehend blockiert ist, was einen Kontextwechsel zu anderen Tasks auslöst.
4
YieldOnce { yielded: false }.await
Setzt den Ausführungsfluss an kooperativen Punkten aus, um eine verschachtelte Task-Ausführung zu ermöglichen.