c++multithreadingasynchronous

Why do we need async and io_context?


I'm studying multithreading, and I came across that it is preferable to use async() with io_context. But I don’t quite understand why they are needed. I re-read several documentations and watched many lectures on this topic, but I still couldn’t figure out what the difference, for example, in this code:

boost::asio::io_context io;

io.post([](){ 
   do_some_work() 
});

std::thread thread([&io]() {
 io.run();
});

from this:

std::thread thread([&io]() {
 do_some_work();
});

I also saw many examples of using io_context with async in client-server interaction with so-called handlers. But I just don’t understand their meaning. Why are they needed if you can just write methods in a row:

socket();
connect();
read();
handle();

Why use a complex async construction with io_context, if you can write everything structurally (as I did above) using future/promise and it will be readable and understandable?


Solution

  • With synchronous socket calls you can only handle one connection per thread, in general it takes much longer to send and receive data over the network than it takes to process the data, this leads to the thread spending most of its time being idle waiting for operations to complete. In a server handling lots of connections, creating a new thread for every connection could be inefficient, threads are generally relatively expensive to create and maintain.

    Asynchronous code helps solve this problem, a thread can do the processing for a connection then asynchronously send the results, whilst it's waiting for the send to complete the thread can go and handle a different connection. This means that you can handle many connections at once with just a small pool of threads.

    io_context is the asio implementation of this thread pool. In your trivial example, yes there is no benefit to using it but a more realistic example would be:

    boost::asio::io_context io;
    void do_some_work(){
      // Do some asynchronous operation
      // Run the callback for it
      io.post(async_complete());
    }
    for (int i = 0; i< 10; i++)
    {
      io.post([](){ 
         do_some_work() 
      });
    }
    
    std::thread thread([&io]() {
     io.run();
    });