A part of our discussion accidentally went private, so I am reposting it
here:
śr., 29 gru 2021 o 17:48 Richard Hodges
On Wed, 29 Dec 2021 at 16:04, Andrzej Krzemienski
wrote: śr., 29 gru 2021 o 15:26 Richard Hodges via Boost
napisał(a): <snip>
Thank you for the quick reply.
So, my question is: does ASIO give a guarantee that it destroys the
completion handler after the preceding operations have finished?
Asio will perform the following operations when about to invoke a completion handler:
- extract the handler from its surrounding async operation via std::move (assuming C++11 or better, otherwise it copies it). - destroy/deallocate any dynamic state in the async operation. - invoke the handler. - destroy the handler.
This assumes that the completion handler is invoked prior to the destruction of the execution context with which it is associated (the normal case).
Yes.
In the corner case of the execution context being destroyed, all outstanding async operations (which would include pending completion handlers) are destroyed.
So, I am not sure how many corner cases there are. One would be to destroy the execution context (like io_context).
This is the only one. If you stop() the io_context but do not destroy it, the outstanding async operations and completion handlers stay alive until either they are allowed to complete (after calling resume()).
I understand that requesting a cancellation of an asynchronous operation is also a kind of special case: we do not expect the completion handler to be invoked. (Am I right?)
No, we expect the completion handler to be invoked either:
a) with the error code asio::error::operation_aborted, in the case that our cancellation signal was noticed prior to the operation's completion, or b) with the result of the operation (whether success or failure) in the case where our cancellation happened after the completion handler of the current operation(s) were posted to the execution context for invocation.
I imagine that in order to provide the cancellation guarantee as expressed in https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/overview/core/canc... the framework still needs to execute some instructions. These final cleanup instructions might still require resources that the user provided (like the socket). The implementation might first execute these cleanup instructions and then destroy the completion handler, or do the opposite: first destroy the completion handler and then call the cleanup instructions. The resource handling strategy with the unique_ptr in the completion handler will work correctly in the first case, but not in the second. So, I would need an additional guarantee that says that the asynchronous operation performs no logic (other than the call to destructor) after destroying the completion handler -- even in the event of cancellation. Or maybe the resource-handling strategy in my example is not supported?
Think of cancellation as a request to cancel. Whether the cancellation signal landed in time, or whether the operation agreed to cancel itself can be discovered when the completion handler is invoked, which is _always_ expected unless you have stopped the execution context.
Thank you for the clarification. Regards, &rzej;
Regards, &rzej;
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
śr., 29 gru 2021 o 16:04 Andrzej Krzemienski
śr., 29 gru 2021 o 15:26 Richard Hodges via Boost
napisał(a): <snip>
Thank you for the quick reply.
So, my question is: does ASIO give a guarantee that it destroys the
completion handler after the preceding operations have finished?
Asio will perform the following operations when about to invoke a completion handler:
- extract the handler from its surrounding async operation via std::move (assuming C++11 or better, otherwise it copies it). - destroy/deallocate any dynamic state in the async operation. - invoke the handler. - destroy the handler.
This assumes that the completion handler is invoked prior to the destruction of the execution context with which it is associated (the normal case).
Yes.
In the corner case of the execution context being destroyed, all outstanding async operations (which would include pending completion handlers) are destroyed.
So, I am not sure how many corner cases there are. One would be to destroy the execution context (like io_context). I understand that requesting a cancellation of an asynchronous operation is also a kind of special case: we do not expect the completion handler to be invoked. (Am I right?) I imagine that in order to provide the cancellation guarantee as expressed in https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/overview/core/canc... the framework still needs to execute some instructions. These final cleanup instructions might still require resources that the user provided (like the socket). The implementation might first execute these cleanup instructions and then destroy the completion handler, or do the opposite: first destroy the completion handler and then call the cleanup instructions. The resource handling strategy with the unique_ptr in the completion handler will work correctly in the first case, but not in the second. So, I would need an additional guarantee that says that the asynchronous operation performs no logic (other than the call to destructor) after destroying the completion handler -- even in the event of cancellation. Or maybe the resource-handling strategy in my example is not supported?
Regards, &rzej;
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost