asio underlying behavior in async_receive

Viewed 77

I have worked with asio library for a few projects and have always managed to get it work, but I feel there are somethings of it that I have not entirely/clearly understood so far. I am wondering how async_receive works.

I googled around a bit and had a look at the implementation but didn't understand it quite well. This is the way that I often use async communication:

socket.async_receive(receive_buffer, receiveHandler);

where receiveHandler is the function that will be called upon the arrival of data on the socket. I know that the async_receive call return immediately. So here are my questions:

  1. Does async_receive create a new thread each time it is called? If not, does it mean that there is a thread responsible to waiting for data and when it arrives, it calls the handler function? When does this thread get created?
  2. If I were to turn this call into a recursive call by using a lambda function like this:
void cyclicReceive() {
  // Imagine the whole thing is in a class, so "this" means something here and
  // "receiveHandler" is still a valid function that gets called.
  socket.async_receive(receive_buffer,
    [this](const asio::error_code& error_code, const std::size_t num_bytes) 
    {
       receiveHandler(error_code, num_bytes);
       cyclicReceive();
    });
}

is there any danger of stack overflow? Why not?

I tried to show a minimal example by removing unnecessary details, so the exact syntax might be a bit wrong.

1 Answers
  1. Asio does not create implicitly any new threads. In general it is based on queue of commands. When you call io.run() the framework is taking the commands from the queue and executing them until queue is empty. All the async_ operations in ASIO push new commands to the internal queue.

  2. Therefore there is no risk of stack overflow. Worst possible but not really probable scenario is out_of_memory exception when there is no space left for commands in command queue (which is very unlikely).

Related