fiber-interop

fiber-interop

One way to write concurrent PHP that runs on every event loop.

PHP has fibers since 8.1, and several good event loops built on them: AMPHP, ReactPHP, Revolt, phasync. Each one has its own way to start a task, wait for it, sleep, and wait for a stream. A library that wants to be asynchronous today picks one loop and loses the users of the others.

fiber-interop is the small layer that removes that choice. A handful of functions, one adapter per runtime, and a conformance suite that every adapter must pass identically:

use function async\{run, go, await_all};

[$a, $b] = run(function () {
    $a = go(fn() => fetch('https://example.com/a'));
    $b = go(fn() => fetch('https://example.com/b'));
    return await_all([$a, $b]);
});

run() is the only entry point: it guarantees the event loop is running for the code inside it and returns when that code and everything it started have finished.

The same code runs unchanged on each supported loop. Install the api and the adapter for the loop you already use; nothing else in your application changes.

What this is

What this is not

Principles

  1. The surface is small and stops growing. A standard that changes is not one.
  2. Semantics are tested, not described. Every rule in the specification is a runnable example with expected output. Adapters are certified by running them.
  3. Interoperability by convention, not by a shared scheduler. A suspension primitive asked to park a fiber it does not own runs its own loop in place instead. Loops that follow this rule work together. Today's loops were not built for it, so each adapter needs one small addition from its runtime, named in that adapter's README; until then the adapters make do, and say how.
  4. Existing code keeps its behaviour. Nothing here changes what a program does when it does not use it. That applies to the Scope RFC as well: code outside a scope sees what it sees today.
  5. Owned by the loops it serves. Adapters are meant to be maintained by the projects they adapt. The api is owned jointly.

Status

Early, 0.1. The api, the Scope extension and polyfill, and adapters for AMPHP, phasync, ReactPHP, Revolt, Swoole and OpenSwoole are on Packagist and pass the whole conformance suite; the matrix at https://fiber-interop.github.io/conformance.html is rebuilt daily. Read api/README.md for the specification, and an adapter's README for how it maps.

Issues and pull requests are welcome in each repository. Maintainers of event loops: if you want to own the adapter for your loop, open an issue in it and say so.

Install

composer require fiber-interop/api fiber-interop/<adapter>

Replace <adapter> with the package for the loop you use.

Runtimes

Integrations

Links