-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a method to the mpsc::Receiver for producing a non-blocking iterator #34724
Conversation
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 commit adds a non-blocking iterator to complement the `try_recv` method, just as the blocking iterator complements the `recv` method.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Thanks for the PR! I was pretty skeptical at first glance but I think your description has won me over. My only heistation is the fact that we're hiding whether iteration was terminated due to "would block" or "disconnected", but perhaps that's not so bad in the long run? If a channel is disconnected then any attempt to receive on it again will again receive a disconnection cc @rust-lang/libs |
@alexcrichton thanks for taking a look!
I attempted to make sure that this behaviour is clear in the new iterator's docs, but perhaps I could also add a note that recommends using |
@mitchmindtree ah yeah the docs are definitely quite clear in this regard, I was just hoping we could surface it at the API level as well (but I'm not sure that's possible here) |
Thanks for the good writeup. Looks fine to me. |
I'm happy to land this API on an unstable basis. |
Discussed during libs triage the decision was to merge, thanks again for the PR @mitchmindtree! @bors: r+ |
📌 Commit b02b38e has been approved by |
⌛ Testing commit b02b38e with merge 376e0f9... |
💔 Test failed - auto-linux-64-opt |
Ahh, I'm missing the |
Ah yeah that'd do it, if you want to open an issue I'll be sure to tag it appropriately and you can update this PR to reference it. |
…ver_try_iter stability attributes
⌛ Testing commit aed2e5c with merge 72dae88... |
💔 Test failed - auto-win-msvc-64-opt-rustbuild |
Looks like a failure perhaps in the tests? On Wed, Jul 20, 2016 at 11:20 AM, bors [email protected] wrote:
|
… instead of break from the loop
Ahh sorry about that @alexcrichton, I just made the fix and successfully ran the tests locally - should be good to go now! |
@bors: r+ No worries! |
📌 Commit 05af033 has been approved by |
⌛ Testing commit 05af033 with merge dbc9edd... |
💔 Test failed - auto-win-gnu-32-opt |
@bors: retry sorry for the number of retries... On Thu, Jul 21, 2016 at 11:47 AM, bors [email protected] wrote:
|
…ichton 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.
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 thetry_recv
method, just as the blocking iterator complements therecv
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 thempsc::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 therecv
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.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:
or wrap the
try_recv
call in aRange<usize>
/FilterMap
iterator combo.On the other hand, this PR would allow for the following:
I imagine this might also be useful to game devs, embedded or anyone doing message passing across real-time threads.