

这是一个纯引擎内部机制的 RFC,不添加任何 PHP 可见的类、函数、常量或语法。它的目的是在 PHP 引擎层面建立一个可插拔的协程调度器接口(ABI),让扩展可以提供调度器,从而激活 PHP 的并发执行模式。
注意:这里说的"并发"是单线程协作式的,不是多线程并行。所有执行流都在一个 OS 线程内,通过协程切换实现交错执行。
RFC:https://wiki.php.net/rfc/async_scheduler_abi
引擎与调度器之间通过六个通知点(notifications)交互。引擎自己不调度,所有调度决策都由调度器通过通知的返回值来做出。
通知 | 触发时机 | 调度器职责 |
|---|---|---|
Launch | 调度器启动时(脚本第一行前,或注册时) | 返回一个"主协程"对象,顶层脚本在其中运行 |
Suspend | 当前执行流挂起,把控制权交还给调度器 | 管理就绪队列,决定接下来运行哪个协程;主协程结束时需返回一个新的主协程给后续代码(如析构函数、shutdown 函数) |
Enqueue | 协程变为可运行状态(新建或恢复) | 将协程加入就绪队列;可附带一个错误(用于取消、超时、I/O 失败) |
Foreign Fiber | 第三方代码创建的 Fiber 启动时(调度器已激活) | 决定是"收养"该 fiber 到自己的调度中,还是让它保持为普通低层 fiber |
Defer | 一次性微任务被提交时 | 在下一个调度 tick 中执行该任务 |
Shutdown | 并发需要提前终止时(如某个协程调用了 exit()) | 停止接受新工作,决定是完成剩余协程还是取消它们 |
created → queued → running → suspended → finished,可循环。引擎为每个协程维护两个存储,解决全局状态在并发下的安全问题:
ob_start() 的处理器栈、gethostbyname() 的结果缓冲区等。存储机制已实现,但将
ob_start()等核心子系统迁移到 per-coroutine 状态是后续工作。
方面 | 影响 |
|---|---|
无调度器注册时 | PHP 行为完全不变,零成本 |
Fiber 库(ReactPHP/Revolt/AMPHP) | 现有代码无需改动;调度器可选择"收养"它们的 fiber,让它们运行在同一个调度上 |
调试工具(Xdebug 等) | 协程执行上下文基于现有 Fiber 机制,step debugging 和堆栈跟踪继续工作 |
Opcache / JIT | 无影响,无新 opcode |
SAPI(CLI/FPM 等) | 无可见影响 |
Fiber::suspend() 在析构函数中抛出错误Fiber::suspend() 会抛出 FiberError。gc_collect_cycles() 可能因新原因返回 0 专用协程被取消,或无法创建专用协程时,返回 0。pcntl_fork() 默认抛出错误,除非调度器注册了专门的 fork 处理程序。这个 RFC 刻意保持最小化,只定义引擎与调度器的接缝。以下属于后续工作:
spawn()、await()、channels、futures、Async\ 命名空间等