Hical 协程入门:告别回调地狱,用 co_await 写异步 C++

Hical 协程入门:告别回调地狱,用 co_await 写异步 C++ 传统 C++ 异步编程离不开回调嵌套、状态机、手动生命周期管理——代码写得像意大利面。C++20 协程从根本上改变了这一切:异步代码写起来和同步一样直观,编译器帮你管理暂停与恢复。本文从零讲解如何在 Hical 框架中使用协程,不需要你懂 Boost.Asio 底层。 什么是协程?30 秒版本 传统回调式: 1 2 3 4 5 6 7 8 9 10 11 12 // 回调嵌套——"回调地狱" socket.async_read(buffer, [&](error_code ec, size_t n) { if (!ec) { socket.async_write(buffer, [&](error_code ec2, size_t) { if (!ec2) { socket.async_read(buffer, [&](error_code ec3, size_t) { // 继续嵌套... }); } }); } }); 协程式: 1 2 3 4 // 同样的逻辑,协程版——像写同步代码一样 auto n = co_await socket.async_read(buffer, use_awaitable); co_await socket.async_write(buffer, use_awaitable); auto n2 = co_await socket.async_read(buffer, use_awaitable); co_await 会暂停当前函数,等 I/O 完成后自动恢复执行。没有回调,没有嵌套,错误用 try/catch 处理。 Hical 对协程做了什么封装? Hical 在 Coroutine.h 中提供了三个核心工具: ...

May 5, 2026 · 4 min · 762 words

告别回调地狱:在 C++ Web 框架中全面拥抱协程

告别回调地狱:在 C++ Web 框架中全面拥抱协程 本文以 Hical 框架为例,展示如何用 C++20 协程 + Boost.Asio 构建一个全协程化的 HTTP 服务器,以及这样做的工程权衡。 回调有什么问题? 几乎所有 C++ 网络框架的 1.0 版本都是回调驱动的。一个简单的"读取请求 → 处理 → 发送响应"流程,回调版本长这样: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void onAccept(tcp::socket socket) { auto buf = std::make_shared<flat_buffer>(); auto req = std::make_shared<http::request<string_body>>(); http::async_read(socket, *buf, *req, [&socket, buf, req](error_code ec, size_t) { if (ec) return; auto res = std::make_shared<http::response<string_body>>(); // ... 处理请求,构建响应 ... http::async_write(socket, *res, [&socket, res](error_code ec, size_t) { if (ec) return; socket.shutdown(tcp::socket::shutdown_send); }); }); } 问题很明显: ...

April 12, 2026 · 3 min · 539 words

深入学习 C++20 协程(Coroutines)

深入学习 C++20 协程(Coroutines) 头文件:<coroutine> 命名空间:std 编译器要求:GCC 11+ / Clang 14+ / MSVC 19.28+(均需 -std=c++20 或以上) 注意:GCC 10 / Clang 8~13 可通过 -fcoroutines 和 <experimental/coroutine> 使用实验性支持 一、为什么需要协程? 1.1 异步编程的传统痛点 游戏服务器中充斥着异步操作——数据库查询、网络 I/O、定时器回调。传统方案各有各的痛: 方案 A:回调地狱(Callback Hell) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void HandleLogin(Connection* conn, const LoginPacket& pkt) { // 第1步:查询数据库验证账号 dbManager->QueryAsync("SELECT * FROM accounts WHERE name=?", pkt.name, [conn, pkt](const DBResult& result) { if (!result.ok) { conn->SendError("DB错误"); return; } // 第2步:查询角色列表 dbManager->QueryAsync("SELECT * FROM characters WHERE account_id=?", result.accountId, [conn](const DBResult& charResult) { if (!charResult.ok) { conn->SendError("DB错误"); return; } // 第3步:加载角色数据 dbManager->QueryAsync("SELECT * FROM inventory WHERE char_id=?", charResult.charId, [conn, charResult](const DBResult& invResult) { // 第4步:终于可以发送登录成功了... conn->SendLoginSuccess(charResult, invResult); }); }); }); } 方案 B:状态机(State Machine) ...

April 8, 2026 · 22 min · 4611 words