Skip to content

Instantly share code, notes, and snippets.

@nggit
Last active January 14, 2024 21:18
Show Gist options
  • Save nggit/4419705331f008d0c00b329c48906fad to your computer and use it in GitHub Desktop.
Save nggit/4419705331f008d0c00b329c48906fad to your computer and use it in GitHub Desktop.
A simple event loop with Fibers (PHP 8 >= 8.1.0)
<?php
// a simple event loop with Fibers (PHP 8 >= 8.1.0)
// in a style slightly inspired by Python's asyncio
// this will not immediately increase the throughput of your code
// since the functions are still executed sequentially in the event loop
// unless you can combine it with a non-blocking stream/socket
// to create the impression of io parallelism
class Loop
{
// defered tasks
public static $tasks = [];
public static function createTask($coro)
{
$fiber = new Fiber(function () use ($coro) {
// defer
Fiber::suspend();
return $coro();
});
$fiber->start();
self::$tasks[] = $fiber;
return $fiber;
}
public static function await($fiber)
{
while (!$fiber->isTerminated()) {
// yield the current task until an awaited task is done
Fiber::suspend();
}
return $fiber->getReturn();
}
public static function run($coro = null)
{
// optionally create a main task
if (is_callable($coro)) {
self::createTask($coro);
}
// event loop
while (self::$tasks) {
$fiber = array_shift(self::$tasks);
if ($fiber->isSuspended() && !$fiber->isTerminated()) {
// execute defered tasks
$fiber->resume();
}
if (!$fiber->isTerminated()) {
// reschedule
self::$tasks[] = $fiber;
}
}
}
}
// coroutines
$coro1 = function () {
return 'Task 1' . PHP_EOL;
};
$coro2 = function () {
return 'Task 2' . PHP_EOL;
};
// tasks
$task1 = Loop::createTask($coro1);
$task2 = Loop::createTask($coro2);
$main = function () use ($task1, $task2) {
echo Loop::await($task2);
echo Loop::await($task1);
echo 'Main task', PHP_EOL;
};
echo 'Before event loop', PHP_EOL;
var_dump(Loop::$tasks);
// run the event loop
Loop::run($main);
echo 'After event loop', PHP_EOL;
var_dump(Loop::$tasks);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment