1

When performing the following piece of code


boost::asio::socket s{...};

auto f1 = s.async_read(..., boost::asio::use_future);
auto f2 = s.async_write(..., boost::asio::use_future);

given that with use_future we do not really specify the context, of where the promise will be set with result value - does this mean that 2 tasks could be running in different threads? and there is no guarantee on single-threadness(use must ensure thread-safety) here?

thanks!

Viktor Khristenko
  • 863
  • 1
  • 5
  • 17

1 Answers1

1

As the comment says, the executor of the IO object (s) will be used for the completion. So all the guarantees of that executor apply.

If you have an execution context that is being polled (run or poll) from a single thread, that thread will be definition set the value or exception on the promise associated with the returned future. Interestingly, it doesn't really matter as std::future is already thread safe and the internal promise isn't shared.

With regards to having two asynchronous operations in flight, that has nothing to do with the completion token. The restrictions documented for the IO object apply. In the case of sockets at most one read and one write operation are allowed to be in flight at any given moment.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • the reason for the question is that it is possible to construct an executor from the provided completion token (use_future here) and not use execution context specified in the constructor. I understand that this is not the case for socket impl, but in general, it is possible that such a thing happens (for another impl of something...). https://www.boost.org/doc/libs/1_81_0/doc/html/boost_asio/example/cpp20/operations/callback_wrapper.cpp – Viktor Khristenko Mar 01 '23 at 09:57
  • 1
    It is *not* possible to construct an executor from `asio::use_future`. It **is** possible to have a completion token bound with _an associated executor_, e.g. one wrapped on a strand. `asio::use_future` does not have that. The fallback depends on context: for operations involving IO objects, the bound executor thereof will be taken, otherwise `system_executor` will be used, see e.g. [here](https://stackoverflow.com/a/52460852/85371) and [here](https://stackoverflow.com/a/66733239/85371) – sehe Mar 01 '23 at 13:57
  • I guess I did not phrase correctly - indeed, __not construct__ but rather somehow obtain one... and the default behavior is probably what I was after... – Viktor Khristenko Mar 02 '23 at 09:37
  • 1
    Yes. You can verify the default being `system_executor` indirectly: http://coliru.stacked-crooked.com/a/546776fe96d4ab22 – sehe Mar 02 '23 at 21:48