
Description
While we can't implement zero-capacity channels based on futures as faithfully as they are in crossbeam-channel
and Go, we can do something very similar. Here's a proposal.
Our zero-capacity channel could be implemented as a channel that has the capacity of 1, except that every send operation does not complete until its message is received.
The problem here is that send operations are not cleanly cancelable. Once a send operation has put its message into the channel, a receive operation can take it. If the Send
future is then dropped, the send operation is not really canceled because someone has already picked up the message.
This issue will come up if we're selecting over send operations:
futures::select! {
_ = s1.send(msg1) => {}
_ = s2.send(msg2) => {}
}
Here it's possible for both send operations to be executed simultaneously. But maybe that's fine and not a big issue since selection over send operation is rare.
Fortunately, selection over receive operation is still cleanly cancellable:
futures::select! {
msg1 = r1.recv() => {}
msg2 = r2.recv() => {}
}
Exactly one receive operation will complete here, which is what the user would probably expect. We can't make the same guarantee about send operations on zero-capacity channels, though.
Is this an acceptable compromise? What does everyone think?
cc @matklad