I have a sequence of nested async operations on an asio::ip::tcp::socket and I want to have a possibility to stop it as fast as possible from an other thread. Here is some pseudo:
socket->async_something(buffer, CallbackLambdaHeader
{
    if (errorcode)
    {
        //exit the sequence
    }
    // some code
    socket->async_something(buffer, CallbackLambdaHeader
    {
        if (errorcode)
        {
            //exit the sequence
        }
        // some code
        socket->async_something(buffer, CallbackLambdaHeader
        {
            if (errorcode)
            {
                //exit the sequence
            }
            // etc
        });
    });
});
The problem is that a simple socket->cancel() call wont always work because in the moment of the call one of the callbacks may be running. So there will be no enqueued operations to cancel, but a running callback can add one soon and continue the sequence.
I want the async operations after socket->cancel() to be cancelled too (instantly complete with operation_aborted error).
The only idea is to somehow wrap every call in a mutex.lock() and use a cancellation flag
//thread1:
mutex.lock();
cancel = true;
socket->cancel();
mutex.unlock();
//thread 2:
mutex.lock();
if (!cancel)
{
    socket->async_something(buffer, CallbackLambdaHeader
    {
        if (errorcode)
        {
            //exit the sequence
        }
        // some code
        mutex.lock();
        if (!cancel)
        {
            socket->async_something(buffer, CallbackLambdaHeader
            {
                if (errorcode)
                {
                    //exit the sequence
                }
                // some code
                mutex.lock();
                if (!cancel)
                {
                    socket->async_something(buffer, CallbackLambdaHeader
                    {
                        if (errorcode)
                        {
                            //exit the sequence
                        }
                        // etc
                    });
                }
                else
                {
                    //exit the sequence
                }
                mutex.unlock();
            });
        }
        else
        {
            //exit the sequence
        }
        mutex.unlock();
    });
}
else
{
    //exit the sequence
}
mutex.unlock();
But it looks awful.
Have heard about io_service::strand, but not sure how to use it here. Use .post() with the socket->cancel() method? Is there any guarantee that situation {callback, cancel, callback} is impossible?
 
    