59 lines
1.6 KiB
Rust

use async_task::{Builder, Runnable};
use flume::unbounded;
use smol::future;
use std::sync::atomic::{AtomicUsize, Ordering};
#[test]
fn metadata_use_case() {
// Each future has a counter that is incremented every time it is scheduled.
let (sender, receiver) = unbounded::<Runnable<AtomicUsize>>();
let schedule = move |runnable: Runnable<AtomicUsize>| {
runnable.metadata().fetch_add(1, Ordering::SeqCst);
sender.send(runnable).ok();
};
async fn my_future(counter: &AtomicUsize) {
loop {
// Loop until we've been scheduled five times.
let count = counter.load(Ordering::SeqCst);
if count < 5 {
// Make sure that we are immediately scheduled again.
future::yield_now().await;
continue;
}
// We've been scheduled five times, so we're done.
break;
}
}
let make_task = || {
// SAFETY: We are spawning a non-'static future, so we need to use the unsafe API.
// The borrowed variables, in this case the metadata, are guaranteed to outlive the runnable.
let (runnable, task) = unsafe {
Builder::new()
.metadata(AtomicUsize::new(0))
.spawn_unchecked(my_future, schedule.clone())
};
runnable.schedule();
task
};
// Make tasks.
let t1 = make_task();
let t2 = make_task();
// Run the tasks.
while let Ok(runnable) = receiver.try_recv() {
runnable.run();
}
// Unwrap the tasks.
smol::future::block_on(async move {
t1.await;
t2.await;
});
}