如何将基于IOCP的协程调度器零基础深入浅出C语言20协程成?
摘要:将真实的异步 IO 事件与协程相结合、例子规模控制在 200 行、能编译能运行的 Windows C++20 协程 demo,见过没?今天就给各位老铁整一个,它还支持多协程并发哦~
前言
上一篇《基于 epoll 的协程调度器》谈到如何基于 epoll 构建一个事件驱动的协程调度器,没有使用三方库的原因主要是为了避免引入额外复杂度,不过只演示 Linux 未免对非 Unix 平台的小伙伴有所不公,为此本文基于 Windows 的完成端口 (IO Completion Port:IOCP) 构建相同能力的 demo。
文章仍然遵守之前的创作原则:
* 选取合适的 demo 是头等大事
* 以协程为目标,涉及到的新语法会简单说明,不涉及的不旁征博引
* 若语法的原理非常简单,也会简单展开讲讲,有利于透过现象看本质,用起来更得心应手
上一篇文章里不光引入了基于事件的调度器,还说明了如何开启多文件并行、await_suspend 与试读的关系、singalfd 用于完美退出等话题,如果没有这些内容铺垫,看本文时会有很多地方难以理解,还没看过的小伙伴,墙裂建议先看那篇。
工具还是之前介绍过的 Compile Explorer,这里不再用到 C++ Insights ,主要是它不支持 Windows 平台,其实 Compiler Explorer 也只是编译,运行的话还是不太行,因为它的环境不支持像文件、网络之类的异步 IO,需要用户自行搭建开发环境。
基于完成端口的 IO 多路复用
上文中提到了 Unix 系统中多路复用接口的发展历程:分别经历了 select -> poll -> epoll/kqueue,Windows 则通过完成端口一统江山,其实它俩调用方式差不太多:
epoll
IOCP
初始化
epoll_create
CreateIoCompletionPort
关联句柄
epoll_ctl
CreateIoCompletionPort
等待并获取下一个事件
epoll_wait
GetQueuedCompletionStatus
投递事件
n/a (self pipe trick)
PostQueuedCompletionStatus
销毁
close
CloseHandle
而在可等待对象上,IOCP 则丰富的多:
* 文件 I/O 事件
* 文件系统变更
* 套接字(Socket)事件
* 命名管道(Named Pipe)事件
* 设备 I/O 事件
* 定时器事件(结合 Waitable Timer)
这方面能与它相提并论的恐怕只有 kqueue 了。
