Skip to content

Commit fc50add

Browse files
committed
Ensure fibers are available and provide helpful error message
1 parent 698d4de commit fc50add

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

examples/http-client-suspension.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ function fetch(string $url): string
5454
return $buffer;
5555
}
5656

57-
function extractHeader(string $httpResponse): string {
58-
return explode("\r\n\r\n", $httpResponse, 2)[0];
57+
function extractHeader(string $httpResponse): string
58+
{
59+
return \explode("\r\n\r\n", $httpResponse, 2)[0];
5960
}
6061

6162
echo extractHeader(fetch('http://www.google.com/'));

src/EventLoop.php

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
final class EventLoop
1919
{
2020
private static Driver $driver;
21-
private static ?\Fiber $fiber;
21+
private static ?\Fiber $fiber = null;
2222

2323
/**
2424
* Sets the driver to be used as the event loop.
@@ -112,7 +112,7 @@ public static function defer(callable $callback): string
112112
* The created callback MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
113113
* right before the next tick. Callbacks MUST NOT be called in the tick they were enabled.
114114
*
115-
* @param float $delay The amount of time, in seconds, to delay the execution for.
115+
* @param float $delay The amount of time, in seconds, to delay the execution for.
116116
* @param callable(string) $callback The callback to delay. The `$callbackId` will be invalidated before
117117
* the callback invocation.
118118
*
@@ -133,7 +133,7 @@ public static function delay(float $delay, callable $callback): string
133133
* The created callback MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
134134
* right before the next tick. Callbacks MUST NOT be called in the tick they were enabled.
135135
*
136-
* @param float $interval The time interval, in seconds, to wait between executions.
136+
* @param float $interval The time interval, in seconds, to wait between executions.
137137
* @param callable(string) $callback The callback to repeat.
138138
*
139139
* @return string A unique identifier that can be used to cancel, enable or disable the callback.
@@ -201,7 +201,7 @@ public static function onWritable(mixed $stream, callable $callback): string
201201
* The created callback MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
202202
* right before the next tick. Callbacks MUST NOT be called in the tick they were enabled.
203203
*
204-
* @param int $signo The signal number to monitor.
204+
* @param int $signo The signal number to monitor.
205205
* @param callable(string, int) $callback The callback to execute.
206206
*
207207
* @return string A unique identifier that can be used to cancel, enable or disable the callback.
@@ -347,6 +347,7 @@ public static function getDriver(): Driver
347347
{
348348
/** @psalm-suppress RedundantPropertyInitializationCheck, RedundantCondition */
349349
if (!isset(self::$driver)) {
350+
self::checkFiberSupport();
350351
self::setDriver((new DriverFactory())->create());
351352
}
352353

@@ -362,10 +363,7 @@ public static function createSuspension(): Suspension
362363
{
363364
/** @psalm-suppress RedundantPropertyInitializationCheck */
364365
if (!isset(self::$fiber) || self::$fiber->isTerminated()) {
365-
if (!\class_exists(\Fiber::class, false)) {
366-
throw new \Error("Fibers required to create loop suspensions");
367-
}
368-
366+
self::checkFiberSupport();
369367
self::$fiber = self::createFiber();
370368
}
371369

@@ -383,14 +381,7 @@ public static function createSuspension(): Suspension
383381
*/
384382
public static function run(): void
385383
{
386-
if (!\class_exists(\Fiber::class, false)) {
387-
if (self::getDriver()->isRunning()) {
388-
throw new \Error("The event loop is already running");
389-
}
390-
391-
self::getDriver()->run();
392-
return;
393-
}
384+
self::checkFiberSupport();
394385

395386
if (\Fiber::getCurrent()) {
396387
throw new \Error(\sprintf("Can't call %s() within a fiber (i.e., outside of {main})", __METHOD__));
@@ -417,6 +408,31 @@ private static function createFiber(): \Fiber
417408
return new \Fiber([self::getDriver(), 'run']);
418409
}
419410

411+
private static function checkFiberSupport(): void
412+
{
413+
if (!\class_exists(\Fiber::class, false)) {
414+
if (\PHP_VERSION_ID < 80000) {
415+
throw new \Error(
416+
"revolt/event-loop requires fibers to be available. " .
417+
"You're currently running PHP " . \PHP_VERSION . " without fiber support. " .
418+
"Please upgrade to PHP 8.1 or upgrade to PHP 8.0 and install ext-fiber from https://github.com/amphp/ext-fiber."
419+
);
420+
}
421+
422+
if (\PHP_VERSION_ID >= 80000 && \PHP_VERSION_ID < 80100) {
423+
throw new \Error(
424+
"revolt/event-loop requires fibers to be available. " .
425+
"You're currently running PHP " . \PHP_VERSION . " without fiber support. " .
426+
"Please upgrade to PHP 8.1 or install ext-fiber from https://github.com/amphp/ext-fiber."
427+
);
428+
}
429+
430+
throw new \Error(
431+
"revolt/event-loop requires PHP 8.1 or ext-fiber. You are currently running PHP " . \PHP_VERSION . "."
432+
);
433+
}
434+
}
435+
420436
/**
421437
* Disable construction as this is a static class.
422438
*/

0 commit comments

Comments
 (0)