asio::io_context
O Asio possui uma classe chamada asio::io_context que é usada para gerenciar operações de entrada e saída assíncronas em um programa de computador. Ela é usada para monitorar e gerenciar operações de entrada e saída em vários descritores de arquivo e sockets, permitindo que o programa seja notificado quando os dados estão disponíveis para leitura ou quando os dados podem ser escritos sem bloquear o processador.
A asio::io_context é geralmente usada em conjunto com um objeto executor_work_guard, que é responsável por manter o loop de eventos da asio::io_context rodando mesmo quando não há operações pendentes.
O conceito é baseado na API de rede do Unix. O Asio também possui o conceito "socket", mas isso não é suficiente: um objeto io_context é necessário para se comunicar com os serviços de E/S do sistema operacional.
Nota histórica: A classe
io_servicefoi o nome antigo deio_context. Ela foi renomeada e está obsoleta — use sempreio_contextem código novo.
A imagem abaixo mostrará a estrutura da Arquitetura Asio:

io_context deriva de execution_context:
class io_context
: public execution_context
{
......
}
Enquanto execution_context deriva de noncopyable:
class execution_context
: private noncopyable
{
......
}
Isso significa que o objeto io_context não pode ser copiado. Portanto, durante a inicialização do socket, ou seja, associar o socket ao io_context, o io_context deve ser passado como referência.
Ex.:
asio::io_context io_context;
asio::ip::tcp::socket socket{io_context}; // io_context passado por referência
Além de gerenciar operações de entrada e saída assíncronas, a asio::io_context também fornece uma série de outras funcionalidades úteis. Por exemplo, ela permite que o programa agende operações para serem executadas em um momento futuro, permitindo que o programa execute tarefas de forma assíncrona de acordo com um cronograma. Ela também permite que o programa cancele operações que estão em andamento.
A asio::io_context pode ser configurada para escalonar operações em vários threads, permitindo que elas sejam executadas em paralelo e aproveitando ao máximo o poder de processamento do computador:
// Sugestão de concorrência para o io_context — pode otimizar internamente
asio::io_context ctx{std::thread::hardware_concurrency()};
A seguir, estão descritas todas as funções comuns do asio::io_context:
-
run: Inicia o loop de eventos doasio::io_context. Bloqueia o thread atual até que todas as operações agendadas tenham sido concluídas ou oio_contextseja interrompido. -
poll: Similar à funçãorun, mas não bloqueia o thread atual. Em vez disso, processa todas as operações prontas noasio::io_contexte retorna imediatamente. -
run_one: Similar à funçãorun, mas processa apenas uma operação pendente antes de retornar. -
poll_one: Similar à funçãopoll, mas processa apenas uma operação pronta antes de retornar. -
stop: Interrompe o loop de eventos doasio::io_context. Útil quando o programa precisa sair antes que todas as operações pendentes sejam concluídas. -
restart: Reinicia oasio::io_contextapós ter sido interrompido comstop(), permitindo que ele aceite novas operações. Deve ser chamado antes de uma nova chamada arun().
Atenção: Em versões antigas do Asio, esta função se chamava
reset(). O nomereset()está depreciado — userestart()em código novo.
-
stopped: Retornatruese oasio::io_contextfoi interrompido comstop(). -
get_executor: Retorna um objeto executor que pode ser usado para agendar operações para serem executadas noasio::io_context.
asio::post e asio::dispatch
Em versões modernas do Asio, as operações de agendamento são realizadas através de funções livres que recebem um executor como primeiro parâmetro:
-
asio::post(executor, fn): Agenda a funçãofnpara ser executada de forma assíncrona no contexto do executor. A função nunca é executada diretamente na chamada — sempre é enfileirada. -
asio::dispatch(executor, fn): Agenda a funçãofnpara ser executada no contexto do executor. Se o chamador já estiver dentro do contexto do executor, a função pode ser executada imediatamente (in-line).
asio::io_context ctx;
// Agenda uma tarefa para execução assíncrona
asio::post(ctx, [] {
std::cout << "Executando de forma assíncrona\n";
});
ctx.run();
Atenção: As formas antigas
io_context.post(fn)eio_context.dispatch(fn)estão depreciadas. Useasio::post(ctx, fn)easio::dispatch(ctx, fn).
executor_work_guard
A classe asio::executor_work_guard é usada para manter o loop de eventos da asio::io_context rodando mesmo quando não há operações pendentes. Isso é essencial quando você quer que a thread do io_context continue viva aguardando trabalho futuro (por exemplo, em um servidor que usa múltiplas threads).
#include <asio.hpp>
#include <thread>
#include <iostream>
int main()
{
asio::io_context ctx;
// Mantém o io_context vivo mesmo sem operações pendentes
auto guard = asio::make_work_guard(ctx);
std::thread worker([&ctx] {
ctx.run(); // bloqueia aqui até o guard ser liberado
});
// Faz algum trabalho...
asio::post(ctx, [] { std::cout << "Tarefa executada!\n"; });
// Libera o guard para permitir que ctx.run() retorne
guard.reset();
worker.join();
return 0;
}
Atenção: A classe
asio::io_context::worke a macro-based work guard estão depreciadas. Useasio::make_work_guard(ctx)que retorna umexecutor_work_guard<io_context::executor_type>.