← SEARCHABLE ARCHIVE
C / C++ · 2026-08-15

C++ de los fundamentos al dominio — Lección 21

Comprender suspensión, reanudación, vida útil y cancelación de coroutines

INTERACTIVE READING MODE →

Los artículos de este blog se han escrito con fines didácticos. Pueden contener errores; contrasta la información con el compilador y la biblioteca estándar de tu plataforma.

Una coroutine puede suspender una función y reanudarla después desde el mismo estado. No crea hilos ni I/O asíncrono automáticamente; es un protocolo del lenguaje para construir control asíncrono.

El estado vive en el Coroutine frame

Al usar co_await, co_yield o co_return, el compilador transforma la función en una máquina de estados que conserva variables locales y el punto de reanudación.

Task<Texture> LoadTextureAsync(Path path)
{
    FileBytes bytes = co_await ReadFileAsync(path);
    DecodedImage image = co_await DecodeAsync(std::move(bytes));
    co_return UploadTexture(std::move(image));
}

Task y los awaitables del ejemplo son contratos definidos por el proyecto o una biblioteca. C++20 estándar define la transformación de coroutines, pero no incluye un executor universal ni un event loop de red.

co_await pregunta cómo suspender

await_ready   ¿Está listo el resultado sin suspensión?
await_suspend ¿Quién posee el handle y lo reanuda?
await_resume  ¿Qué valor o error se produce después?

Si el trabajo terminó, la ejecución puede continuar. En caso contrario, el Coroutine handle debe entregarse de forma segura al scheduler o I/O y reanudarse exactamente una vez.

La propiedad del frame decide la vida útil

Si el llamador descarta el Task, ¿la operación se cancela, se separa o queda en otro propietario? Un callback que reanuda un frame destruido causa use-after-free.

Las referencias también pueden expirar durante la suspensión.

Task<void> ShowLater(const Player& player)
{
    co_await NextFrame();
    Draw(player.Name); // ¿Sigue vivo player?
}

Copia los datos necesarios al frame, usa handles estables o expresa la garantía de vida del llamador.

La cancelación y los errores también son protocolos. Cancelar debe despertar operaciones, permitir limpieza y propagar un resultado. El promise type decide si una excepción se guarda y relanza en co_await o se convierte en un valor de error.

Las coroutines se leen como código secuencial, pero actúan en varios momentos. Documenta propiedad del frame, executor, hilo de reanudación, cancelación y propagación, y prueba la implementación de Task que realmente uses.