-
-
Save SerafimArts/4ce7f67052fefd5efcabdcb96bb00847 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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