Skip to content
This repository was archived by the owner on Jun 16, 2025. It is now read-only.

Commit 48622d0

Browse files
committed
Enhance documentation and comments on coroutine management, emphasizing scope usage and cancellation behavior
1 parent 9cef994 commit 48622d0

File tree

1 file changed

+29
-8
lines changed

1 file changed

+29
-8
lines changed

basic.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,8 +1331,8 @@ spawn with $scope {
13311331
spawn {
13321332
spawn {
13331333
throw new Exception("Error occurred");
1334-
};
1335-
};
1334+
};
1335+
};
13361336
};
13371337

13381338
try {
@@ -1349,7 +1349,7 @@ Error occurred
13491349
```
13501350

13511351
The `await $scope` expression can be used multiple times
1352-
because `$scope` acts as a trigger that can transition to a completed state multiple times:
1352+
because `$scope` acts as a **trigger** that can transition to a completed state multiple times:
13531353

13541354
```php
13551355
$scope = new Scope();
@@ -1485,13 +1485,22 @@ function connectionLimiter(callable $cancelToken): void
14851485

14861486
function connectionHandler($socket): void
14871487
{
1488-
$scope = Scope::inherit();
1489-
1488+
// Note that a parent Scope can stop the execution of all coroutines
1489+
// belonging to a child Scope at any moment.
1490+
$scope = Scope::inherit();
1491+
1492+
//
1493+
// Passing `$scope` via `use` into a single coroutine is equivalent to the logic:
1494+
// the lifetime of `$scope` equals the lifetime of the coroutine.
1495+
// In this way, we create a coroutine-closure that acts as a Point of Responsibility.
1496+
// This code is one example of how to implement Points of Responsibility.
1497+
//
14901498
spawn with $scope use($socket, $scope) {
14911499

14921500
$limiterScope = Scope::inherit(); // child scope for connectionLimiter and connectionChecker
14931501

1494-
$cancelToken = fn(string $message) => $scope->cancel(new CancellationException($message));
1502+
// We do not provide direct access to the Scope object in other functions, because this is an antipattern!
1503+
$cancelToken = fn(string $message) => $scope->cancel(new CancellationException($message));
14951504

14961505
// Limiter coroutine
14971506
spawn with $limiterScope connectionLimiter($cancelToken);
@@ -1505,26 +1514,37 @@ function connectionHandler($socket): void
15051514
fwrite($socket, "HTTP/1.1 500 Internal Server Error\r\n\r\n");
15061515
} finally {
15071516
fclose($socket);
1517+
// Explicitly cancel all coroutines in the child scope
15081518
$scope->cancel();
15091519
}
15101520
};
15111521
}
15121522

15131523
function socketServer(): void
15141524
{
1525+
// Main Server $scope
15151526
$scope = new Scope();
15161527

15171528
// Child coroutine that listens for a shutdown signal
1529+
//
1530+
// Note that we are passing `$scope` to another function!
1531+
// This is acceptable here because the code is within a single visual block,
1532+
// and the risk of an error due to oversight is minimal.
15181533
spawn with $scope use($scope) {
15191534
try {
1535+
// Note: The `signal` function is not part of this RFC,
1536+
// but it may be implemented in the standard library in the future.
1537+
// This example shows how such a function could be used.
1538+
// The `signal` function returns a trigger `Awaitable`.
15201539
await Async\signal(SIGINT);
15211540
} finally {
15221541
$scope->cancel(new CancellationException('Server shutdown'));
15231542
}
15241543
}
15251544

15261545
try {
1527-
// Main coroutine that listens for incoming connections
1546+
// The main coroutine that listens for incoming connections
1547+
// The server runs as long as this coroutine is running.
15281548
await spawn with $scope {
15291549
while ($socket = stream_socket_accept($serverSocket, 0)) {
15301550
connectionHandler($socket);
@@ -1538,7 +1558,8 @@ function socketServer(): void
15381558
// Graceful exit
15391559
try {
15401560
$scope->cancel();
1541-
await $scope until Async\timeout(5);
1561+
// Await for all coroutines to finish but not more than 5 seconds
1562+
await $scope until Async\timeout(5000);
15421563
echo "Server stopped\n";
15431564
} catch (\Throwable $exception) {
15441565
// Force exit

0 commit comments

Comments
 (0)