You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have found some strange and unexpected behavior with functions like future::zip and future::race when used together. I always expected that some future and async { future.await } should behave the same. But I realized that this is not the case.
Minimal code example:
use smol::{
channel::{Receiver,Sender},
future,};asyncfnproduct(tx:Sender<u32>){for i in0..20{if tx.send(i).await.is_err(){break;}println!("sent {i}");}}asyncfnconsume(n:u32,rx:Receiver<u32>){println!("start task #{n}");whileletOk(i) = rx.recv().await{if i == 5{println!("exit");break;}println!("received {i}");}}// Create a channel with minimum buffer size to reproduce the problem more clearlylet(tx, rx) = smol::channel::bounded(1);let a = consume(1, rx.clone());let b = consume(2, rx);let tasks = future::race(a, b);
smol::block_on(future::zip(product(tx), tasks));
If you run this code it will stuck.
My expectation is once one of the tasks completes, it will end the entire race and drop all receivers. Then the sender will see its receivers have been dropped, then it will exit its loop and will drop with completing the entire zip. But it seems that it doesn't work because zip doesn't drop its futures until all of them are completed.
But I can wrap tasks in an additional future like this:
- let tasks = future::race(a, b);+ let tasks = async { future::race(a, b).await };
And now it works as expected. After one task completes, all others complete after and the code no longer stucks.
However, I think it's not intuitive. It would be better if zip will drop completed futures itself.
The text was updated successfully, but these errors were encountered:
I have found some strange and unexpected behavior with functions like
future::zip
andfuture::race
when used together. I always expected that somefuture
andasync { future.await }
should behave the same. But I realized that this is not the case.Minimal code example:
If you run this code it will stuck.
My expectation is once one of the tasks completes, it will end the entire
race
and drop all receivers. Then the sender will see its receivers have been dropped, then it will exit its loop and will drop with completing the entirezip
. But it seems that it doesn't work becausezip
doesn't drop its futures until all of them are completed.But I can wrap tasks in an additional future like this:
And now it works as expected. After one task completes, all others complete after and the code no longer stucks.
However, I think it's not intuitive. It would be better if
zip
will drop completed futures itself.The text was updated successfully, but these errors were encountered: