Commit 0d75975
authored
Auto merge of rust-lang#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.1 file changed
+56
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
314 | 325 | | |
315 | 326 | | |
316 | 327 | | |
| |||
982 | 993 | | |
983 | 994 | | |
984 | 995 | | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
985 | 1006 | | |
986 | 1007 | | |
987 | 1008 | | |
| |||
1077 | 1098 | | |
1078 | 1099 | | |
1079 | 1100 | | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
1080 | 1108 | | |
1081 | 1109 | | |
1082 | 1110 | | |
| |||
1814 | 1842 | | |
1815 | 1843 | | |
1816 | 1844 | | |
| 1845 | + | |
| 1846 | + | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
| 1851 | + | |
| 1852 | + | |
| 1853 | + | |
| 1854 | + | |
| 1855 | + | |
| 1856 | + | |
| 1857 | + | |
| 1858 | + | |
| 1859 | + | |
| 1860 | + | |
| 1861 | + | |
| 1862 | + | |
| 1863 | + | |
| 1864 | + | |
| 1865 | + | |
| 1866 | + | |
| 1867 | + | |
| 1868 | + | |
| 1869 | + | |
| 1870 | + | |
| 1871 | + | |
| 1872 | + | |
1817 | 1873 | | |
1818 | 1874 | | |
1819 | 1875 | | |
| |||
0 commit comments