对于螺纹应用程序,Rust Standard库提供 std :: Sync :: mpsc :: Sync_channel
,一种缓冲通道,当缓冲区为空时,该通道会阻止阅读结束,并且在缓冲区的写作结束时会阻止。已满。特别是,如果将缓冲区大小设置为0,则任何读取或写入都会阻塞,直到有匹配的写入或读取为止。
对于异步代码,有 Futures :: Channel :: MPSC :: Channel
,但这没有相同的行为。在这里,最小容量是频道上发件人的数量,大于0。发送端仍然可以阻止(因为它实现了 sink
,因此我们可以使用 sinkext :: send 和等待
IT),但仅在缓冲区中至少有一件事之后。
我看了看是否有任何包装提供我想要的功能,但我找不到任何东西。 tokio
提供了许多不错的异步同步基原始人,但是它们都没有做到我想要的。另外,我的程序将在浏览器中运行,因此我认为我无法使用 tokio
的运行时。有人知道适合我用例的软件包吗?我会自己尝试实现此功能,因为这几乎感觉就像 sink
和流
特征最小的用例真的很复杂。想法?
编辑:这是我的意思的最小示例:
fn main() {
let (tx, rx) = blocking_channel();
let ft = async move {
tx.send(3).await;
println!("message sent and received");
}
let fr = async move {
let msg = rx.recv().await;
println!("received {}", msg);
}
block_on(async { join!(ft, fr) });
}
在此示例中,首先运行的未来将屈服于另一个,并且仅在 rx.Recv
和 tx.send
被打电话给。显然,接收端只能在调用 tx.send
之后进行进展,但是我希望传输端的不太明显行为也必须等待。
For threaded applications, the Rust standard library provides std::sync::mpsc::sync_channel
, a buffered channel which blocks on the reading end when the buffer is empty and blocks on the writing end when the buffer is full. In particular, if you set the buffer size to 0, then any read or write will block until there is a matching write or read.
For async code, there is futures::channel::mpsc::channel
, but this does not have the same behavior. Here the minimum capacity is the number of senders on the channel, which is greater than 0. The sending end can still block (because it implements Sink
, so we can use SinkExt::send
and await
it), but only after there's at least one thing already in the buffer.
I took a look to see if there were any packages that provide the functionality I'm looking for, but I could not find anything. Tokio
provides lots of nice async synchronization primitives, but none of them did quite what I'm looking for. Plus, my program is going to run in the browser, so I don't think I'm able to use a runtime like Tokio
. Does anyone know of a package that fits my use case? I would try to implement this myself, since this almost feels like the most minimal use case for the Sink
and Stream
traits, but even a minimal implementation of these traits seems like it would be really complicated. Thoughts?
Edit: here's a minimal example of what I mean:
fn main() {
let (tx, rx) = blocking_channel();
let ft = async move {
tx.send(3).await;
println!("message sent and received");
}
let fr = async move {
let msg = rx.recv().await;
println!("received {}", msg);
}
block_on(async { join!(ft, fr) });
}
In this example, whichever future runs first will yield to the other, and only print after both rx.recv
and tx.send
have been called. Obviously, the receiving end can only progress after tx.send
has been called, but I want the less obvious behavior of the transmitting end also having to wait.
发布评论
评论(1)
有趣的问题。我认为没有类似的东西已经存在。
这是我为此写的快速概念验证原型。这不是最漂亮的,但似乎有效。不仅将所有内容包装在
refcell< option< ...>>
中。而且我并不特别喜欢sender_dropped
和receiver_dropped
变量。请确保如果在生产中使用!
Interesting question. I don't think something like that already exists.
Here is a quick proof-of-concept prototype I wrote for that. It's not the prettiest, but it seems to work. There might be a better struct layout than just wrapping everything in a
RefCell<Option<...>>
, though. And I don't particularly like thesender_dropped
andreceiver_dropped
variables.Be sure to unittest it properly if used in production!!!