boostorg / process

Boost Process
https://www.boost.org/libs/process
115 stars 113 forks source link

Move from using asio::io_context to asio::executor for constructing async types #88

Open complexmath opened 5 years ago

complexmath commented 5 years ago

boost::asio has been moving away from using io_context for initialization to the more generally defined executor type, and in 1.70 the deprecated socket.get_io_context() is gone entirely. As boost::process remains unchanged in this regard, code that relied on being able to get the io_context from sockets and such as a means of initializing async_pipes no longer compiles. Consider moving towards accepting an executor instead.

klemens-morgenstern commented 5 years ago

What code part relies on getting an io_context from sockets?

complexmath commented 5 years ago

async_pipe is initialized via an io_context. In server code, for example, if I want to initialize an async_pipe while processing a client request, and I want to be sure that pipe is initialized with the same io_context the socket is using, so events serialize properly, the most practical approach is to use socket.get_io_context(). Except this is gone now.

Since boost::asio is moving away from using io_context towards executors in general though, it seems like boost::process should follow suit, if for no other reason than to do things in the intended manner. I can only guess that asio is moving towards having different executor specializations for different uses.

klemens-morgenstern commented 5 years ago

Ah ok, well that changes to socket.get_executor().context().

Thing is: async_pipe uses the posix::stream_handle or the windows equivalent under the hood. They still take a context.

I feel like changing this for async_pipe would break a lot of peoples code.

complexmath commented 5 years ago

socket.get_executor().context() returns a different type which is a parent class (or template sibling maybe) of io_context. I'd be fine passing that in instead of an executor. I just don't want to have to try and downcast to io_context, which is what I'd need to do today.

amerry commented 2 years ago

Thing is: async_pipe uses the posix::stream_handle or the windows equivalent under the hood. They still take a context.

According to the link you gave, they take an executor (like the other ASIO types, they can also take an io_context for backwards compatibility, but the documented API pushes you towards using an executor).

maxtruxa commented 1 year ago

This is really annoying when working with coroutines, where you can easily retrieve the active executor from this_coro::executor but there is no way to get back to an io_context from that.

namespace asio = boost::asio;
namespace bp = boost::process;

asio::awaitable<void> something() {
    auto executor = co_await asio::this_coro::executor;
    asio::steady_timer t{executor}; // example
    bp::async_pipe pipe{???}; // ...
}

The workaround is obviously to pass a reference to the io_context around, but that is now only necessary for Boost.Process and super annoying when it's deep within the application.

asio::awaitable<void> something(asio::io_context& ioc) {
    bp::async_pipe pipe{ioc}
}
klemens-morgenstern commented 1 year ago

I developed process.v2 since the this issue was opened, so that should help. Note that asio has pipes now as well, in case you don't need processes.

maxtruxa commented 1 year ago

Oh, somehow I assumed "v2" is what's in the v2 branch (which has the same issue) without looking at the docs... My bad. V2 works a treat!

rhapsodyv commented 6 months ago

I was having the same issue and this worked for me:

boost::asio::io_context io;
boost::asio::any_executor ex(io);
....
....
boost::asio::io_context &io_context = ex.target<boost::asio::io_context::executor_type>()->context();