最佳实践(Best Practices)
本节给出在使用 koroutine_lib 时的若干建议,覆盖协程生命周期、取消、调度器选择、性能调优与调试技巧。
1. 协程生命周期与结构化并发
- 优先使用
when_all/Runtime::join_all等结构化并发原语来限定协程的生命周期,避免“火箭发射器式”的后台任务(无控制的长期驻留任务)。 - 对于短生命周期的辅助任务,使用
details::FireAndForget或者明确start()并保证在作用域退出前有合适的取消/等待逻辑。
2. 取消(Cancellation)
- 使用库提供的
CancellationToken(见include/koroutine/cancellation.hpp)进行合作式取消,而不是强行终止线程。 - 在可能长时间挂起的 awaiter(IO/睡眠/Channel)处检测取消标志并尽早返回。
3. 调度器与执行器选择
- CPU 密集型任务应当提交到计算线程池(可通过自建
AsyncExecutor或类似机制),I/O 密集型任务优先使用IO Scheduler(默认通过SchedulerManager提供)。 - 对于需要线程亲和性(如访问非线程安全资源或 UI 更新),使用
LooperExecutor并通过co_await switch_to(looper_executor)切换到该上下文。
4. 性能优化
- 减少频繁的
start()/resume()切换,尽量把短任务合并在同一协程内完成; - 避免在执行器线程内做大量阻塞操作,除非该执行器专门用于阻塞 I/O;
- 对于高频调用路径,考虑减少堆分配和 std::function 的动态分配(可以在未来用 folly/boost 的小函数优化替代);
5. 调试与日志
- 启用
KOROUTINE_DEBUG宏可以打印更详细的运行时信息(见include/koroutine/debug.h); - 使用
ScheduleMetadata::debug_name在调度点传递可读的任务标识,以便在日志中归因。
6. API 兼容性与版本策略
- 如果你计划将来支持 C++26 的
std::execution能力,建议在库中增加适配层(adapter),而不是把内部实现替换为std::execution。 - 保持
Task/Awaiter的 API 稳定,避免在 minor 版本中破坏调用约定。