Re: PHP True Async RFC - Stage 2

From: Date: Mon, 17 Mar 2025 11:02:14 +0000
Subject: Re: PHP True Async RFC - Stage 2
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-126802@lists.php.net to get a copy of this message
# BoundedScope I tried to refine the BoundedScope class to its logical completeness, considering your feedback. However, I no longer like it because it now resembles an advanced ComposeFuture or BoundedFuture (I'm not even sure which one). There is no doubt that such functionality is needed, but I have concerns about the design. It seems better to implement BoundedFuture separately (placing it in a dedicated RFC) and incorporate this logic there, while BoundedScope might not be necessary at all. Essentially, the code using BoundedScope could be replaced with: ```php $scope = new Scope(); $future = BoundedFuture(); try { await $future; } finally { $scope->dispose(); } ``` On the other hand, a method like spawnAndProlong could be useful if there is a need to implement a pattern where the Scope remains alive as long as at least one task is active. But is this case significant enough to keep it? I'm not sure. I need some time to process this. In the meantime, I'll show you the draft I came up with. #### BoundedScope The BoundedScope class is designed to create explicit constraints that will be applied to all coroutines spawned within the specified Scope. The BoundedScope class implements the following pattern: ```php $scope = new Scope(); $constraints = new Future(); $scope->spawn(function () use($constraints) { try { await $constraints; } finally { \Async\currentScope()->cancel(); } }); ``` Here, $constraints is an object implementing the Awaitable interface. Once it completes, the Scope will be terminated, and all associated resources will be released. | Method | Description | |----------------------------------------|-------------------------------------------------------------------------------------------------------------| | defineTimeout(int $milliseconds) | Define a specified timeout, automatically canceling coroutines when the time expires. | | spawnAndBound(callable $coroutine) | Spawns a coroutine and restricts the lifetime of the entire Scope to match the coroutine’s lifetime. | | spawnAndProlong(callable $coroutine) | Spawns a coroutine and extends the lifetime of the entire Scope to match the coroutine’s lifetime. | | boundedBy(Awaitable $constraint) | Limits the scope’s lifetime based on a **Cancellation token, Future, or another coroutine's lifetime**. | | prolongedBy(Awaitable $constraint) | Extends the scope’s lifetime based on a **Cancellation token, Future, or another coroutine's lifetime**. | ```php $scope = new BoundedScope(); $scope->defineTimeout(1000); $scope->spawnAndBound(function() { sleep(2); echo "Task 1\n"; }); await $scope; ``` ##### Prolong and Bound triggers The BoundedScope class operates with two types of triggers: - **Bound trigger** – limits execution time by the minimum boundary.. - **Prolong trigger** – limits execution time by the maximum boundary. For the **Prolong** trigger to execute, all **Prolong** objects must be completed. For the **Bound** trigger to execute, at least one **Bound** object must be completed. The Scope will terminate as soon as either the **Prolong** or **Bound** trigger is executed. ##### defineTimeout The defineTimeout method sets a global timeout for all coroutines belonging to a Scope. The method initializes a single internal timer, which starts when defineTimeout is called. When the timer expires, the Scope::cancel() method is invoked. The defineTimeout method can only be called once; a repeated call will throw an exception. ##### spawnAndBound / spawnAndProlong spawnAndBound creates a coroutine and limits its execution time to the current Scope. The method can be called multiple times. In this case, the Scope will not exist longer than the lifetime of the shortest coroutine. spawnAndProlong creates a coroutine and extends the lifetime of the current Scope to match the coroutine's lifetime. ##### boundedBy / prolongedBy The boundedBy method allows limiting the lifetime of a Scope by explicitly specifying an object that implements the Awaitable interface. The Awaitable interface is inherited by classes such as Coroutine and Scope. Additionally, classes like Future and Cancellation, which are not part of this RFC, can also implement the Awaitable interface.

« previous php.internals (#126802) next »