Auto merge of #34724 - mitchmindtree:mpsc_receiver_try_recv, r=alexcrichton
Add a method to the mpsc::Receiver for producing a non-blocking iterator Currently, the `mpsc::Receiver` offers methods for receiving values in both blocking (`recv`) and non-blocking (`try_recv`) flavours. However only blocking iteration over values is supported. This PR adds a non-blocking iterator to complement the `try_recv` method, just as the blocking iterator complements the `recv` method. Use-case ------------- I predominantly use rust in my work on real-time systems and in particular real-time audio generation/processing. I use `mpsc::channel`s to communicate between threads in a purely non-blocking manner. I.e. I might send messages from the GUI thread to the audio thread to update the state of the dsp-graph, or from the audio thread to the GUI thread to display the RMS of each node. These are just a couple examples (I'm probably using 30+ channels across my various projects). I almost exclusively use the `mpsc::Receiver::try_recv` method to avoid blocking any of the real-time threads and causing unwanted glitching/stuttering. Now that I mention it, I can't think of a single time that I personally have used the `recv` method (though I can of course see why it would be useful, and perhaps the common case for many people). As a result of this experience, I can't help but feel there is a large hole in the `Receiver` API. | blocking | non-blocking | |------------|--------------------| | `recv` | `try_recv` | | `iter` |🙀 | For the most part, I've been working around this using `while let Ok(v) = r.try_recv() { ... }`, however as nice as this is, it is clearly no match for the Iterator API. As an example, in the majority of my channel use cases I only want to check for *n* number of messages before breaking from the loop so that I don't miss the audio IO callback or hog the GUI thread for too long when an unexpectedly large number of messages are sent. Currently, I have to write something like this: ```rust let mut take = 100; while let Ok(msg) = rx.try_recv() { // Do stuff with msg if take == 0 { break; } take -= 1; } ``` or wrap the `try_recv` call in a `Range<usize>`/`FilterMap` iterator combo. On the other hand, this PR would allow for the following: ```rust for msg in rx.try_iter().take(100) { // Do stuff with msg } ``` I imagine this might also be useful to game devs, embedded or anyone doing message passing across real-time threads.
Showing
想要评论请 注册 或 登录