# 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.

Reply via email to