@@ -339,10 +339,10 @@ The `spawn` construct is available in two variations:
339339
340340``` php
341341// Executing a known function
342- spawn [with <scope >] <function _call >;
342+ spawn [with [child] <scope >] <function _call >;
343343
344344// Closure form
345- spawn [with <scope >] [static] [use(<parameters >)][: <returnType >] {
345+ spawn [with [child] <scope >] [static] [use(<parameters >)][: <returnType >] {
346346 <codeBlock >
347347};
348348```
@@ -444,7 +444,7 @@ spawn (fn() => sleep(1))();
444444Allows creating a coroutine from a closure directly when using ` spawn ` :
445445
446446``` php
447- spawn [with <scope >] [static] [use(<parameters >)[: <returnType >]] {
447+ spawn [with [child] <scope >] [static] [use(<parameters >)[: <returnType >]] {
448448 <codeBlock >
449449};
450450```
@@ -530,6 +530,70 @@ spawn with $this->scope $this->method();
530530spawn with $this->getScope() $this->method();
531531```
532532
533+ #### Spawn with child expression
534+
535+ The ` spawn with ` expression allows you to create siblings relative to the specified scope.
536+ However, it can be useful to create a coroutine in a child scope to establish a clear hierarchy.
537+
538+ ``` php
539+ use Async\Scope;
540+
541+ $scope = new Scope();
542+
543+ spawn with $scope wathcher();
544+
545+ spawn with $scope use($scope): void {
546+ foreach ($hosts as $host) {
547+ $child = Scope::inherit($scope);
548+
549+ $coroutine = spawn with $scope {
550+ echo gethostbyname('php.net').PHP_EOL;
551+ };
552+
553+ $coroutine->onComplete(fn() => $child->disposeSafely());
554+ }
555+ };
556+
557+ $scope->awaitAllIgnoringErrors();
558+ ```
559+
560+ ** Structure:**
561+
562+ ```
563+ $scope = new Scope();
564+ ├── watcher() ← runs in the $scope
565+ ├── foreach($hosts) ← runs in the $scope
566+ ├── $child = Scope::inherit($scope)
567+ │ └── subtask1() ← runs in the childScope
568+ ├── $child = Scope::inherit($scope)
569+ │ └── subtask2() ← runs in the childScope
570+ ├── $child = Scope::inherit($scope)
571+ │ └── subtask3() ← runs in the childScope
572+ ```
573+
574+ This structure separates main tasks belonging to the ` $scope ` and child tasks that are launched in child scopes.
575+ Each child task can be cancelled independently of the others, since it belongs to a separate scope (Supervisor pattern).
576+
577+ The ` child ` keyword is used to create a child scope from the specified scope.
578+
579+ ``` php
580+ use Async\Scope;
581+
582+ $scope = new Scope();
583+
584+ spawn with $scope wathcher();
585+
586+ spawn with $scope use($scope): void {
587+ foreach ($hosts as $host) {
588+ spawn with child $scope {
589+ echo gethostbyname('php.net').PHP_EOL;
590+ };
591+ }
592+ };
593+
594+ $scope->awaitAllIgnoringErrors();
595+ ```
596+
533597### Suspension
534598
535599A coroutine can suspend itself at any time using the ` suspend ` keyword:
@@ -2580,7 +2644,14 @@ final class Service
25802644 private function run(): void
25812645 {
25822646 while (($socket = $this->service->receive()) !== null) {
2583- spawn with Scope::inherit($this->scope) $this->handleRequest($socket);
2647+
2648+ $scope = Scope::inherit($this->scope);
2649+
2650+ (spawn with $scope $this->handleRequest($socket))->onCompletion(
2651+ static function () use ($scope) {
2652+ $scope->disposeSafely();
2653+ }
2654+ );
25842655 }
25852656 }
25862657}
0 commit comments