Synchrony goodbye party


In real life a synchronous I/O is almost useless. Even if you write a simple client which deals with a single network connection, your application almost always has other things to do, like UI management, user's input, etc. However synchronous I/O is blocking, which means that your application's control flow will get stuck until current I/O operation is completed.

You can overcome this by creating additional threads. For example, one thread could process I/O while another deal with UI. However that approach will grow complexity of your application since you will need to sychronize control flow of concurrent threads. Moreover, there is no safe way to cancel blocking I/O operation from a different thread. This may work as you expect, however it is not safe in general, and you could face unexpected behavior if something change in your environment (for example, if you compile your code for a new platform that you didn't work with before).

Asynchronous approach is free from these disadvantages. Simply put, asynchronous task execution could be translated to English like that: “Start doing this in background, and when you done, call this function. Meanwhile I will do other things need to be done”. Therefore, asynchronous execution is non-blocking execution, and you can do other things while your tasks are being performed in background. Also asynchronous task can be safely cancelled at any time.

Synchronous approach:

// This will block until we get a message
std::size_t bytes_transferred = socket.receive_from(buffer, sender);
std::cout << "Message is received, message size is " << bytes_transferred;

Asychronous version of I/O functions in Boost.Asio starts with async_ prefix. The same code could be rewritten in an asynchronous manner:

// This will not block - the execution will run along right after the call
socket.async_receive_from(buffer, [&] (boost::system::error_code error, std::size_t bytes_transferred)
    // This lambda will call upon receiving of a message
    std::cout << "Message is received, message size is " << bytes_transferred;

In C++ we like to get everything under control. The first thing you should ask: “Hey, where exactly does this background task run? Do I need to create a thread for it?”. You will get the answer for this question in the next lesson. Meanwhile, it's time to say “goodbye” for a synchronous code and move further.

Share this page:

Learning plan

What should you know before get started
A brief description of the difference between network transport protocols
What is server anyway? The most simple example
4. Synchrony goodbye party
It's time to say “goodbye” to a synchronous I/O
The first simple asynchronous TCP server
How to handle Boost.Asio errors
There are several new things we should learn before jumping into a bigger example of a server