Ok, thanks for the suggestion.


As a side-note, cancellation/shutdown seems to be the least thought-through feature in ASIO..


- it's an all or nothing thing, i.e., it can't be used to cancel individual I/O requests

- it doesn't work on completed requests


.. EVEN THOUGH the io service has a list of outstanding requests (waiting for completion) and pending (completed) handlers.


I could also just call stop() on the io_service, but when it's started again, all the "old" handlers will be called as well. The only complete solution probably being stopping and deleting io_service, and recreating it in the next "go".


-- Stian


From: Boost-users <boost-users-bounces@lists.boost.org> on behalf of Gavin Lambert via Boost-users <boost-users@lists.boost.org>
Sent: Tuesday, January 30, 2018 4:27:46 AM
To: boost-users@lists.boost.org
Cc: Gavin Lambert
Subject: Re: [Boost-users] asio: cancelling a named pipe client
 
On 27/01/2018 06:50, Stian Zeljko Vrba wrote:
> Am I correct in assuming that cancel() is an apparent noop in this case
> because of the race-condition where an I/O request completes
> successfully before cancel is invoked?

Most likely yes.  It just internally calls through to the OS API, which
will have nothing to do if there isn't an outstanding OS request at that
exact moment.

ASIO can't internally consider this a permanent failure because there
may be cases where you wanted to cancel a single operation and then
start a new one that you expect to continue normally.

> If so, can you suggest a more elegant way  (i.e., a way that doesn't
> induce a hard error) of exiting a loop as described here? Setting a
> member variable instead of calling cancel?

Probably the best thing to do is to do both, in this order:

   1. Set a member variable that tells your completion handler code to
not start a new operation.
   2. Call cancel() to abort any pending operation.

This covers both cases; if you miss the pending operation then the
member will tell your completion handler to not start a new one and just
return, and if you don't then the cancellation will generate an
operation_aborted which you can either silently ignore and return
immediately or fall through to the code that checks the member.

There's still a race between when you check the member and when the
operation actually starts -- but that's why you need to post your
cancellation request to the same io_service (and use explicit strands if
you have more than one worker thread).

Omitting the cancel isn't recommended as this would prolong shutdown in
the case that the remote end isn't constantly transmitting.

_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
https://lists.boost.org/mailman/listinfo.cgi/boost-users