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?