Hi internals, I hope you're all doing well. Before putting a formal RFC up for discussion, I'd like to share the idea behind it and ask for your advice on how best to frame it.
The idea -------- Drawing on the implementation experience of the TrueAsync project, the proposal changes the PHP engine so that concurrency can be implemented correctly - by an extension. The core itself gains no scheduler, no reactor, and no event system. Instead, it learns to behave properly when one is present: the main execution flow becomes a coroutine, the garbage collector and the shutdown/destructor machinery become coroutine-aware, and a coroutine context preserves engine state across switches. All scheduling policy lives in a separate Scheduler extension that plugs into a small set of engine slots. Quite a lot of the engine work needed to make this real is already in place: free switching between execution contexts (any coroutine can switch to any other, without the asymmetric restrictions of the Fiber API), a garbage collector that stays correct in the presence of coroutines, and a carefully worked-out object destruction cycle at every stage of the request lifecycle. In short - everything that gives PHP code stability in a concurrent environment. The details are described in this article: https://medium.com/p/d4a38e7f6a08 The long-term goal is full asynchrony in the core: within concurrent code, the standard blocking functions (sleep, file and socket I/O, DNS, streams) become non-blocking transparently, without any changes to existing userland code. Worth mentioning: the reactor side (the I/O event loop) can be seen as a natural continuation of the already accepted Polling API RFC (implemented in PHP 8.6): https://wiki.php.net/rfc/poll_api What the PR currently contains ------------------------------ The implementation branch ships the engine changes plus two reference implementations: 1. A minimal C scheduler (ext/test_scheduler) that drives the test suite. 2. The Scheduler Hook API (ext/async_scheduler_hook) - a bridge that makes it possible to implement a Scheduler directly in PHP: the engine hands coroutine lifecycle events to userland callbacks, and the mandate closures (bindEntry / switchTo / currentCoroutine) give the PHP scheduler control over context switching. Working examples live in the PR itself, e.g. the mini scheduler used by its tests: https://github.com/true-async/php-src/tree/async-core/ext/async_scheduler_hook/tests Materials, if you'd like to take a closer look: Article on the design: https://medium.com/p/d4a38e7f6a08 RFC draft: https://github.com/true-async/php-async-core-rfc/blob/main/scheduler_rfc.md Pull request: https://github.com/php/php-src/pull/22561 Implementation branch: https://github.com/true-async/php-src/tree/async-core Where I would appreciate advice ------------------------------- My current inclination is to propose only the engine-side changes and not to include the Scheduler Hook API in the core. My reasoning is simple: if something isn't required by the core and PHP works without it, there's no reason to ship it in the core. However, that leaves me with an RFC that contains no user-visible changes to PHP at all - no new classes, no new functions, no new syntax. I'm honestly not sure how such an RFC is best presented, so I'd be grateful for your thoughts on a few questions: 1. Is an RFC the right vehicle for changes that are purely internal to the engine (essentially an ABI for extensions)? Is there a precedent for framing one this way? 2. If so, what should the RFC text focus on - the engine behavior changes, the ABI contract, or both? 3. Should the Scheduler Hook bridge be mentioned in the RFC as an illustration of how the ABI can be used, or left out entirely? Of course, any feedback on the design itself is very welcome as well. Thank you for your time - I really appreciate it. Best regards, Edmond
