Skip to content

Instantly share code, notes, and snippets.

@SerafimArts
Last active June 28, 2020 22:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SerafimArts/4ce7f67052fefd5efcabdcb96bb00847 to your computer and use it in GitHub Desktop.
Save SerafimArts/4ce7f67052fefd5efcabdcb96bb00847 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
final class EventLoop
{
/**
* @var \Generator[]|array[]
*/
private iterable $iterators = [];
/**
* @var self|null
*/
private static ?self $instance = null;
private function __construct()
{
\register_shutdown_function(static function () {
(self::$instance ??= new self())->run();
});
}
/**
* @param Closure $callback
* @return void
*/
public static function push(\Closure $callback): void
{
(self::$instance ??= new self())->add($callback);
}
/**
* @param Closure $callback Это вполне может быть промизом или генертором, а не анонимкой.
* @return $this
*/
public function add(\Closure $callback): self
{
/** @var \Generator $iterator */
$this->iterators[] = $callback(); // Магия превращения коллбека в генератор.
// А можно и без распаковки сразу же пушить генератор.
return $this;
}
/**
* @return iterable|\Generator[]
*/
private function fetch(): iterable
{
while (\count($this->iterators)) {
foreach ($this->iterators as $i => $iterator) {
if (! $iterator->valid()) {
unset($this->iterators[$i]);
continue;
}
yield $iterator => $iterator->current();
}
}
}
/**
* @return void
*/
private function run(): void
{
foreach ($this->fetch() as $ctx => $value) {
if ($value instanceof \Closure) {
$ctx->send($value());
continue;
}
$ctx->next();
}
}
}
<?php
declare(strict_types=1);
function async(\Closure $fn)
{
EventLoop::push($fn);
}
async(static function() {
// yield => await
echo yield fn(): int => 1;
echo yield fn(): int => 3;
});
async(static function() {
echo yield fn(): int => 2;
echo yield fn(): int => 4;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment