use futures::channel::oneshot; use futures::executor::LocalPool; use futures::future::{self, lazy, poll_fn, Future}; use futures::task::{Context, LocalSpawn, LocalSpawnExt, Poll, Spawn, SpawnExt, Waker}; use std::cell::{Cell, RefCell}; use std::pin::Pin; use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::thread; use std::time::Duration;
letmut pool = LocalPool::new(); let spawn = pool.spawner();
let waker: Rc<Cell<Option<Waker>>> = Rc::new(Cell::new(None));
{ let cnt = cnt.clone(); let waker = waker.clone();
spawn
.spawn_local_obj( Box::pin(poll_fn(move |ctx| {
cnt.set(cnt.get() + 1);
waker.set(Some(ctx.waker().clone())); if cnt.get() == ITER {
Poll::Ready(())
} else {
Poll::Pending
}
}))
.into(),
)
.unwrap();
}
for i in0..ITER - 1 {
assert_eq!(cnt.get(), i);
assert!(!pool.try_run_one());
assert_eq!(cnt.get(), i + 1); let w = waker.take();
assert!(w.is_some());
w.unwrap().wake();
}
assert!(pool.try_run_one());
assert_eq!(cnt.get(), ITER);
}
#[test] fn try_run_one_runs_sub_futures() { letmut pool = LocalPool::new(); let spawn = pool.spawner(); let cnt = Rc::new(Cell::new(0));
let inner_spawner = spawn.clone(); let cnt1 = cnt.clone();
spawn
.spawn_local_obj( Box::pin(poll_fn(move |_| {
cnt1.set(cnt1.get() + 1);
// also add some pending tasks to test if they are ignored
spawn.spawn_local_obj(Box::pin(pending()).into()).unwrap();
}
assert_eq!(cnt.get(), i * PER_ITER);
pool.run_until_stalled();
assert_eq!(cnt.get(), (i + 1) * PER_ITER);
}
}
#[test] #[should_panic] fn nesting_run() { letmut pool = LocalPool::new(); let spawn = pool.spawner();
// Tests that the use of park/unpark in user-code has no // effect on the expected behavior of the executor. #[test] fn park_unpark_independence() { letmut done = false;
let future = future::poll_fn(move |cx| { if done { return Poll::Ready(());
}
done = true;
cx.waker().clone().wake(); // (*) // some user-code that temporarily parks the thread let test = thread::current(); let latch = Arc::new(AtomicBool::new(false)); let signal = latch.clone();
thread::spawn(move || {
thread::sleep(Duration::from_millis(10));
signal.store(true, Ordering::SeqCst);
test.unpark()
}); while !latch.load(Ordering::Relaxed) {
thread::park();
}
Poll::Pending // Expect to be called again due to (*).
});
/// Regression test for https://github.com/rust-lang/futures-rs/pull/2593 /// /// The issue was that self-waking futures could cause `run_until_stalled` /// to exit early, even when progress could still be made. #[test] fn self_waking_run_until_stalled() { let wakeups_remaining = Rc::new(RefCell::new(10));
letmut pool = LocalPool::new(); let spawner = pool.spawner(); for _ in0..3 { let wakeups_remaining = Rc::clone(&wakeups_remaining);
spawner.spawn_local(SelfWaking { wakeups_remaining }).unwrap();
}
// This should keep polling until there are no more wakeups.
pool.run_until_stalled();
assert_eq!(*wakeups_remaining.borrow(), 0);
}
/// Regression test for https://github.com/rust-lang/futures-rs/pull/2593 /// /// The issue was that self-waking futures could cause `try_run_one` /// to exit early, even when progress could still be made. #[test] fn self_waking_try_run_one() { let wakeups_remaining = Rc::new(RefCell::new(10));
letmut pool = LocalPool::new(); let spawner = pool.spawner(); for _ in0..3 { let wakeups_remaining = Rc::clone(&wakeups_remaining);
spawner.spawn_local(SelfWaking { wakeups_remaining }).unwrap();
}
spawner.spawn(future::ready(())).unwrap();
// The `ready` future should complete.
assert!(pool.try_run_one());
// The self-waking futures are each polled once.
assert_eq!(*wakeups_remaining.borrow(), 7);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.