Skip to content

Adapt boost::asio to stdexec #1501

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

Closed
wants to merge 6 commits into from

Conversation

AnonymousPC
Copy link

@AnonymousPC AnonymousPC commented Mar 25, 2025

  • You can now try async-networking in stdexec.
  • Making boost::asio return senders.
  • Only 1 tiny header file.

Stdexec is advanced and modern, but we haven't yet built a complete networking/IO wheel on top of it. If we integrate boost::asio seamlessly with stdexec, we’ll not only get to experimentally try out networking in stdexec right now, but also help validate some of stdexec’s concepts as a proof.

Changes:

  • asioexec/use_sender.hpp, which is the single-header file to include.
  • 3 example files under asioexec/example, which indicates how it works.

Wishes:

  • Make it as an optional extension in stdexec (similar to execpools/third-party-tools)
  • Move files to a standardized location (e.g., execpools/asio). Currently placed in asioexec just for testing.

Thank you :)

- You can now use async-networking in stdexec.
- Making boost::asio return senders.
- Only 1 tiny header file.

Thank you.
Copy link

copy-pr-bot bot commented Mar 25, 2025

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@ericniebler
Copy link
Collaborator

I've long wanted something like this, thank you! I am no ASIO expert, but I know a few. I have asked one to weigh in on this PR.

@ericniebler
Copy link
Collaborator

/ok to test

@RobertLeahy
Copy link

I like the concept of adapting Asio initiating functions to yield senders, and have implemented something similar in my company's code base.

In addition to the fact this PR doesn't have any unit tests, I also see missing functionality which is crucial to correctly adapt Asio initiating functions to senders.

As far as I can tell the proposed use_sender completion token neglects the fact that Asio asynchronous operations can throw exceptions. When these are thrown they are emitted from the intermediate completion handler being invoked and are handled however the execution context sees fit. This leads to the final completion handler never being invoked which is fine under Asio's model but isn't tolerated under std::execution's model: For an operation which has been started exactly one completion signal must be sent. Therefore use_sender needs to wrap the associated executor, use this wrapping to wrap all submitted intermediate completion handlers, catch all exceptions thrown thereby, and coalesce them to set_error_t(std::exception_ptr).

The next issue directly follows from the above. In addition to throwing exceptions (leading to the final completion handler never being invoked) the Asio model supports what I call "abandonment." You can simply walk away from a running operation, allow the lifetime of the completion handlers to end, and everything is fine. std::execution doesn't tolerate this as described above and therefore use_sender needs to detect abandonment and coalesce it to, for example set_stopped_t().

Lastly on the list of crucial issues is the fact that while Asio supports cancellation via cancellation slots and signals use_sender does not plumb these through into the stop token machinery of std::execution.

As a possible quality of life improvement use_sender should perhaps identify asynchronous operations which complete with boost::system::error_code as the first parameter to the completion handler and coalesce truthy completions to set_error, but perhaps that's best left as a separate algorithm to ensure that "partial success" has its context fully preserved.

@RobertLeahy
Copy link

Also: This PR doesn't seem to account for the fact that Asio asynchronous operations can have multiple completion signatures.

@AnonymousPC
Copy link
Author

AnonymousPC commented Mar 27, 2025

@RobertLeahy Thank you for your excellent feedback and insights -- I really appreciate it :)
Here are the updates addressing the 5 points you raised above:

Point 0: Missing unit tests

  • Okay, Added 3 unit tests in test/asioexec/
  • Created an echo_server example in examples/asioexec/

Point 3: Cancellation

  • Okay, Modified use_sender.hpp to properly propagate cancellation:
    • request_stop() in stdexec now triggers cancellation_slot.emit() in Boost.Asio
    • Tested in test/asioexec/test_use_sender_with_cancellation.cpp

Point 4: Error_code

  • Okay, Enhanced use_sender to:
    • Automatically identify completion tokens returning boost::system::error_code as 1st argument
    • Throw them as exceptions
  • Renamed original implementation to use_nothrow_sender
    • (There might be better names such as use_native_sender use_raw_sender...)

Points 1 & 2: Multiple/Unexecuted boost::asio::completion_tokens

  • Still coding...... will follow up with another commit in a few days :)

@ericniebler
Copy link
Collaborator

i don't know enough about ASIO to weigh the pros and cons of this PR and #1503. are there advantages to this PR in your opinion? we can use your tests and examples regardless.

@AnonymousPC
Copy link
Author

I don't know enough about asio either (in fact, I'm a C++ learner with about one year of experience). #1503 appears more rigorous, cleaner, and demonstrates higher code quality - it likely comes from an ASIO expert.

Feel free to use above tests and examples. I hope they'll help people better understand stdexec.

(Sorry for the late reply - my GitHub account was temporarily suspended due to an automated system error, and I only just saw this comment now.)

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

Successfully merging this pull request may close these issues.

3 participants