Skip to content
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

Feature Request: non-blocking recv() #16

Open
wucke13 opened this issue Jul 17, 2019 · 8 comments
Open

Feature Request: non-blocking recv() #16

wucke13 opened this issue Jul 17, 2019 · 8 comments
Assignees

Comments

@wucke13
Copy link

wucke13 commented Jul 17, 2019

It would be nice to have a way of non-blocking recv(). I think there is many applications for it, just like in std::sync::mpsc::Receiver.

@wucke13
Copy link
Author

wucke13 commented Oct 22, 2019

@tstellanova ping
Also please consider implementing the new async/await feature, as it is even nicer than non blocking recv()

@tstellanova
Copy link
Collaborator

@wucke13 feel free to submit a pull request

@wucke13
Copy link
Author

wucke13 commented Dec 26, 2019

I have looked into this a bit more. AFAIK, there are two ways of accomplishing this:

  • ugly: spawning a new thread, blocking recv() in that thread, push to MPSC, use MPSC try_recv() to get async behavior. That's what I'm currently doing as a hot fix.
  • correct: Adding state to read_versioned_msg(). Detect if buffer is not big enough to parse the message, and return std::io::ErrorKindWouldBlock in that case. Preserve the so far consumed bytes, as they might be part of a valid message. That way it becomes trivial to implement the actual try_recv(). One could orient at tokio's codec trait, for the implementation.

The correct way of doing this involves re-implementing parts of the MAVLink parser. Any chances that you will look into this? Can you confirm my understanding of the possible solutions, or is there a neat way that I'm missing out on?

@tstellanova
Copy link
Collaborator

tstellanova commented Dec 27, 2019 via email

@podhrmic
Copy link
Collaborator

Hi @wucke13 !
I thought about this library as "bare minimum" - i.e. it only provides struct definitions and a couple of convenience functions (socket and serial read for example). What you are mentioning would benefit from using rust futures for example.

That being sad, feel free to submit a PR with your solution, just make sure it is properly feature gated with #[cfg(feature = "...")] (we want the library to be usable even in no-std environments)

@tstellanova I got kind of stuck typechecking enums and implementing a set of sensible quickcheck tests, then I ran out of time. So it is kind of half finished at the moment:-/

@wucke13
Copy link
Author

wucke13 commented Jan 2, 2020

I would oppose to using futures for this. From recent experiment I took away that futures are only beneficial when one build complex dependencies on them. For a simple "give it to me, if and only if its ready" they are not a good fit. I would therefore still prefer the try_recv style interface.

Also, I think try_recv should be considered part of bare minimum. I mean, even the Arduino serial interface offers a an aswer to "How much can I receive". So IMHO even in an absolute bare minimum setup, there should be an non blocking way of asking for new messages.

I'm still not convinced that my understanding is sufficient to make a PR for this, we will see 😄

@patrickelectric
Copy link
Member

Just to update this issue, I'm working to add such feature, probably a PR should be ready in a couple of days, the ideas is to implement something like try_recv as @wucke13 commented, and maybe in the future having something closer to mpsc.

@patrickelectric patrickelectric self-assigned this Jul 4, 2020
@wucke13
Copy link
Author

wucke13 commented Jul 6, 2020

@patrickelectric That is very good news! However, please note: Since I wrote my comment, futures came a long way! Especially with smol the futures thing became much more accessible, at least to me. I think the correct way of doing making the mavlink crate future proof is this:

  • Offering recv() for legacy compatibilitie, and because it is sufficient sometimes
  • Offering try_recv() for simple async-ish stuff. This is important especially for no_std, as it may not be so simple to spawn a real async executor there.
  • Offering async recv(). This is the most useful way of interacting with a message stub, IMO.

Internally, recv() could just await the aysn recv for the sake of simplicity. I don't see any reason so far, why this wouldn't work. That way mavlink.rs can offer a rich and modern API without too much code duplication or other sacrifices.

What do you think about this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants