| Crates.io | tokio-futures-order |
| lib.rs | tokio-futures-order |
| version | 0.1.0 |
| created_at | 2025-10-13 17:43:57.714023+00 |
| updated_at | 2025-10-13 17:43:57.714023+00 |
| description | Enforce execution order of multiple tasks. |
| homepage | |
| repository | https://github.com/arielherself/tokio-futures-order |
| max_upload_size | |
| id | 1880905 |
| size | 19,147 |
This crate provides an interface to notify after a future is polled. This is impossible
to implement without touching the future itself. For example,
let _ = future.await;
notify.notify_one();
does not have the same semantics; it only notifies when the future completes.
There are two options: use OnceOrder for notifying only after the first poll, or
Order for notifying after every poll.
The main use case of this crate is enforcing execution order of multiple tasks when testing. Suppose you want to test your handcrafted queue:
#[tokio::test]
async fn my_test() {
let v = Arc::new(Mutex::new(Vec::new()));
let (sender, receiver) = MyQueue::new();
let task = tokio::spawn({
let v = Arc::clone(&v);
async move {
v.lock().await.push(1);
let _data = receiver.recv().await;
v.lock().await.push(2);
}
});
v.lock().await.push(3);
sender.send(());
task.await.unwrap();
assert_eq!(v.lock().await.as_slice(), &[1, 3, 2]);
}
This code actually produces [3, 1, 2] instead of [1, 3, 2] under a lot of situations,
because the sender.send could happen before the task being polled for the first time. In
that case, you don't test the waiting functionality of your queue; it never actually yields. So
you need to let the producer send data only after the consumer starts waiting. You could use
OnceOrder to achieve this:
use tokio_futures_order::once_order_with;
#[tokio::test]
async fn my_test() {
let v = Arc::new(Mutex::new(Vec::new()));
let (sender, receiver) = MyQueue::new();
let notify = Arc::new(Notify::new());
let notified = notify.clone().notified_owned();
let task = tokio::spawn({
let v = Arc::clone(&v);
async move {
v.lock().await.push(1);
let _data = once_order_with(notify, receiver.recv()).await;
v.lock().await.push(2);
}
});
notified.await;
v.lock().await.push(3);
sender.send(());
task.await.unwrap();
assert_eq!(v.lock().await.as_slice(), &[1, 3, 2]);
}
The code above results in v being [1, 3, 2] as expected.