Reputation: 2161
When using C++20 coroutines with Boost.Asio it is possible to make an operation awaitable with either boost::asio::use_awaitable
or boost::asio::deferred
as in the following examples.
std::size_t n = co_await my_socket.async_read_some(buffer, use_awaitable);
std::size_t n = co_await my_socket.async_read_some(buffer, deferred);
What is the difference and in what situations would you use one rather than the other?
Specifically, I have seen several places on the internet where deferred
is described as higher performance because it "doesn't create a coroutine frame".
[asio::deferred] provides a significant improvement in performance for operations that don’t need the full functionality of the asio::awaitable<> type. https://cppalliance.org/richard/2022/08/10/RichardsAugustUpdate.html
By using asio::deferred you can avoid creation of a new coroutine frame. https://www.reddit.com/r/cpp/comments/10idtq0/an_implementation_of_smpp_protocol_on_boostasio/
The overhead is minimal, specially if you know how to avoid creating unnecessary coroutine frames e.g. use_awaitable vs deferred. https://www.reddit.com/r/cpp_questions/comments/14kq0ew/should_almost_all_new_asio_code_use_coroutines/
Upvotes: 5
Views: 1487
Reputation: 2161
Boost.Asio coroutines work by allocating an awaitable_frame
to store the local variables and then dispatching the execution through the executor.
The use_awaitable
completion token creates a coroutine frame wrapping the async initiation function and returns it.
The deferred
completion token returns a deferred function object. A deferred function is not a coroutine and can be run without using coroutines at all. The asio coroutine promise knows how to dispatch the deferred function to the executor directly without needing to allocate an additional coroutine frame.
Therefore, deferred
really does avoid the creation of an additional coroutine frame.
deferred
should be preferred in general, however the type it returns is obtuse and therefore it can not easily be made part of an API or stored in containers, etc.
The advantage of use_awaitable
is that it always returns an awaitable<>
.
Upvotes: 6