This question is asked from the context of Boost ASIO (C++).
Say you are using a library to do some async i/o on a socket, where:
- you are always waiting to receive data
- you occasionally send some data
Since you are always waiting to receive data (e.g. you trigger another async_read()
from your completion handler), at any given time, you will either have:
- an async read operation in progress
- an async read operation in progress and an async write operation in progress
Now say you wanted to call some other function, on_close()
, when the connection closes. In Boost ASIO, a connection error or cancel()
will cause any oustanding async reads/writes to give an error to your completion handler. But there is no guarantee whether you are in scenario 1. or 2., nor is there a guarantee that the write will error before the read or vice versa. So to implement this, I can only imagine adding two variables called is_reading
and is_writing
which are set to true by async_read()
and async_write()
respectively, and set to false by the completion handlers. Then, from either completion handler, when there is an error and I think the connection may be closing, I would check if there is still an async operation in the opposite direction, and call on_close()
if not.
The code, more or less:
atomic_bool is_writing;
atomic_bool is_reading;
...
void read_callback(error_code& error, size_t bytes_transferred)
{
is_reading = false;
if (error)
{
if (!is_writing) on_close();
}
else
{
process_data(bytes_transferred);
async_read(BUF_SIZE); // this will set is_reading to true
}
}
void write_callback(error_code& error, size_t bytes_transferred)
{
is_writing = false;
if (error)
{
if (!is_reading) on_close();
}
}
Assume that this is a single-threaded app, but the thread is handling multiple sockets so you can't just let the thread end.
Is there a better way to design this? To make sure on_close()
is called after the last async operation finishes?
Aucun commentaire:
Enregistrer un commentaire