Optimal concurrency with async
⚓ Rust 📅 2025-04-29 👤 surdeus 👁️ 9Hello, in most cases I see how to achieve optimal concurrency between dependent task by composing futures in rust.
However, there are cases where I am not quite sure how to do it without having to circumvent the borrow checker, which very reasonably is not able to prove that my code is safe.
Consider for example the following scenario.
first_future_a: requires immutable access toafirst_future_b: requires immutable access tobfirst_future_ab: requires immutable access toaandbsecond_future_a: requires mutable access toa, and must execute afterfirst_future_aandfirst_future_absecond_future_b: requires mutable access tob, and must execute afterfirst_future_bandfirst_future_ab.
I would like second_future_a to be able to run as soon as first_future_a and first_future_ab are completed.
I would also like second_future_b to be able to run as soon as first_future_b and first_future_ab are completed.
For example one may try to write the following code:
let mut a = ...;
let mut b = ...;
let my_future = async {
let first_fut_a = async {
println!("A from first_fut_a: {:?}", a.get()); // immutable access to a
};
let first_fut_b = async {
println!("B from first_fut_ab: {:?}", b.get()); // immutable access to b
};
let first_fut_ab = async {
println!("A from first_fut_ab: {:?}", a.get()); // immutable access to a
println!("B from first_fut_ab: {:?}", b.get()); // immutable access to b
};
let second_fut_a = async {
first_fut_a.await;
first_fut_ab.await;
// This only happens after the immutable refs to a are not used anymore,
// but the borrow checker doesn't know that.
a.increase(1); // mutable access to a, the borrow checker is sad :(
};
let second_fut_b = async {
first_fut_b.await;
first_fut_ab.await;
// This only happens after the immutable refs to b are not used anymore,
// but the borrow checker doesn't know that.
b.increase(1); // mutable access to b, the borrow checker is sad :(
};
future::zip(second_fut_a, second_fut_b).await;
};
Is there a way to make sure that
second_fut_a can run as soon as first_fut_a and first_fut_ab are done, and
second_fut_b can run as soon as first_fut_b and first_fut_ab are done
(whichever happens first) while maintaining borrow checking at compile time (no RefCell please
)?
1 post - 1 participant
🏷️ rust_feed