Closed ashtum closed 1 month ago
async_compose can leverage the same asio::prepend/append
trick we use. However, with async_compose
, you don't control how the executor, allocator, and cancellation slot are propagated to lower async operations. async_compose
will pass to lower async operations the executor, allocator, and cancellation slot that were attached (if any) to the outer completion token. Sometimes, this is not desirable, as you may want to control, for example, which cancellation slot gets propagated to the lower async operation.
This is especially important when you need to implement a "total cancellation" type, where you may not want to immediately cancel a lower async_write
operation but instead cancel the outer handle while allowing the underlying operation to continue. This scenario is particularly relevant in the case of total cancellation, such as with WebSocket. The same happens with MQTT—you must finish the conversation cleanly with the broker, even if someone abruptly cancels the PUBLISH operation in the middle of its execution.
The ability to control exactly what is propagated to lower-level async operations is the main reason we use async_initiate
instead of async_compose
. In many cases within the Async.MQTT5 library, async_compose
and async_initiate
result in the same behavior, but they differ in key areas. We use async_initiate
to maintain consistency throughout.
Thanks for the explanation. That really cleared things up.
Isn't this possible even with composed operations? https://godbolt.org/z/xx1o8Ghxa