boost · high

Boost.Asio: The Proactor Model — async ops & completion handlers

Boost.Asio implements the proactor pattern, in contrast to the reactor model of epoll: with epoll you are told a socket is ready and then perform the read or write yourself, whereas with Asio you initiate the operation (async_read) and the OS — or Asio's emulation over epoll/kqueue/IOCP — actually performs it and then calls your completion handler with the result. An async operation returns immediately, merely registering intent; when the bytes have been transferred Asio queues your handler, which receives an error_code and bytes_transferred, onto the io_context where a thread inside run() invokes it, so the initiating thread is never parked on I/O and a single thread can service thousands of connections. Completion handlers drive the next step — a read handler processes data and initiates a write, whose handler initiates the next read — and this chain of asynchronous operations is effectively your protocol's state machine; you must always inspect the error_code (for example boost::asio::error::eof when the peer closes) before trusting the result.

🔑 Key line

Asio is a PROACTOR: you initiate an async op (async_read/write), the OS performs the I/O, and your completion handler(error_code, bytes_transferred) is later queued on the io_context and invoked by a run() thread. async_* never blocks; chaining handlers (read→process→write→read) forms the protocol state machine. Always check the error_code.

The code

// initiate an async op; returns IMMEDIATELY (never blocks):
boost::asio::async_read(sock, buf,
[](boost::system::error_code ec, std::size_t n) {
// completion handler: runs later, on a run() thread
if (!ec) { /* use n bytes */ }
});

What this lesson walks through

  1. 01Reactor vs Proactor
  2. 02An async op never blocks
  3. 03Chaining handlers = the async state machine

epoll is a REACTOR: it tells you a socket is READY, then YOU perform the read/write. Asio exposes a PROACTOR: you INITIATE the operation (async_read), the OS/Asio actually performs it, and when it's done your completion handler is called with the result. (Under the hood Asio often implements the proactor on top of epoll/kqueue/IOCP.)

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of Boost.Asio: The Proactor Model — async ops & completion handlers and 100+ animated C++ interview lessons.

← Previous
Boost.Asio: io_context & the Event Loop
Next →
Boost.Asio: Strands — Lock-Free Handler Serialization