Ensure timers always yield at least once.
This prevents a task that's constantly running late from monopolizing the CPU. Add executor_fairness_test example showcasing it.
This commit is contained in:
@@ -7,16 +7,21 @@ use crate::time::{Duration, Instant};
|
||||
|
||||
pub struct Timer {
|
||||
expires_at: Instant,
|
||||
yielded_once: bool,
|
||||
}
|
||||
|
||||
impl Timer {
|
||||
pub fn at(expires_at: Instant) -> Self {
|
||||
Self { expires_at }
|
||||
Self {
|
||||
expires_at,
|
||||
yielded_once: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn after(duration: Duration) -> Self {
|
||||
Self {
|
||||
expires_at: Instant::now() + duration,
|
||||
yielded_once: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,11 +30,12 @@ impl Unpin for Timer {}
|
||||
|
||||
impl Future for Timer {
|
||||
type Output = ();
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.expires_at <= Instant::now() {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.yielded_once && self.expires_at <= Instant::now() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
unsafe { super::register_timer(self.expires_at, cx.waker()) };
|
||||
self.yielded_once = true;
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user