Skip to content

Instantly share code, notes, and snippets.

@SerafimArts
Created November 28, 2022 16:22
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/9ba3f4f1e75dad00b22330e12a3e6465 to your computer and use it in GitHub Desktop.
Save SerafimArts/9ba3f4f1e75dad00b22330e12a3e6465 to your computer and use it in GitHub Desktop.
<?php
/**
* @template TArgStart
* @template TArgResume
* @template TArgReturn
* @template TArgSuspend
*
* @param \Fiber<TArgStart, TArgResume, TArgReturn, TArgSuspend> $fiber
* @param TArgStart ...$args
* @return \Generator<array-key, TArgResume, TArgReturn, TArgSuspend>
* @throws \Throwable
*
* @psalm-suppress TooManyTemplateParams
* @psalm-suppress MixedAssignment
*/
function fiber_to_generator(\Fiber $fiber, mixed ...$args): \Generator
{
$index = -1; // Note: Pre-increment is faster than post-increment.
$value = null;
// Allow an already running fiber.
if (!$fiber->isStarted()) {
$value = $fiber->start(...$args);
if (!$fiber->isTerminated()) {
$value = yield ++$index => $value;
}
}
// A Fiber without suspends should return the result immediately.
if (!$fiber->isTerminated()) {
while (true) {
$value = $fiber->resume($value);
// The last call to "resume()" moves the execution of the
// Fiber to the "return" stmt.
//
// So the "yield" is not needed. Skip this step and return
// the result.
if ($fiber->isTerminated()) {
break;
}
$value = yield ++$index => $value;
}
}
return $fiber->getReturn();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment