Good day, Alex.

>
>  Can you please share a bit more details on how the Scheduler is
implemented, to make sure that I understand why this contradiction exists?
Also with some examples, if possible.
>

```php
$fiber1 = new Fiber(function () {
    echo "Fiber 1 starts\n";

    $fiber2 = new Fiber(function () use (&$fiber1) {
        echo "Fiber 2 starts\n";

        Fiber::suspend(); // Suspend the inner fiber
        echo "Fiber 2 resumes\n";

    });

});
```

Yes, of course, let's try to look at this in more detail.
Here is the classic code demonstrating how Fiber works. Fiber1 creates
Fiber2. When Fiber2 yields control, execution returns to Fiber1.

Now, let's try to do the same thing with Fiber3. Inside Fiber2, we create
Fiber3. Everything will work perfectly—Fiber3 will return control to Fiber2,
and Fiber2 will return it to Fiber1—this forms a hierarchy.

Now, imagine that we want to turn Fiber1 into a *Scheduler* while following
these rules.
To achieve this, we need to ensure that all Fiber instances are created
from the *Scheduler*, so that control can always be properly returned.

```php

class Scheduler {
    private array $queue = [];

    public function add(callable $task) {
        $fiber = new Fiber($task);
        $this->queue[] = $fiber;
    }

    public function run() {
        while (!empty($this->queue)) {
            $fiber = array_shift($this->queue);

            if ($fiber->isSuspended()) {
                $fiber->resume($this);
            }
        }
    }

    public function yield() {
        $fiber = Fiber::getCurrent();
        if ($fiber) {
            $this->queue[] = $fiber;
            Fiber::suspend();
        }
    }
}

$scheduler = new Scheduler();

$scheduler->add(function (Scheduler $scheduler) {
    echo "Task 1 - Step 1\n";
    $scheduler->yield();
    echo "Task 1 - Step 2\n";
});

$scheduler->add(function (Scheduler $scheduler) {
    echo "Task 2 - Step 1\n";
    $scheduler->yield();
    echo "Task 2 - Step 2\n";
});

$scheduler->run();

```

So, to successfully switch between Fibers:

   1. A Fiber must return control to the *Scheduler*.
   2. The *Scheduler* selects the next Fiber from the queue and switches to
   it.
   3. That Fiber then returns control back to the *Scheduler* again.

This algorithm has one drawback: *it requires two context switches instead
of one*. We could switch *FiberX* to *FiberY* directly.

Breaking the contract not only disrupts the code in this RFC but also
affects Revolt's functionality. However, in the case of Revolt, you can
say: *"If you use this library, follow the library's contracts and do not
use Fiber directly."*

But PHP is not just a library, it's a language that must remain consistent
and cohesive.

>
>  Reading the RFC initially, I though that the Scheduler is using fibers
for everything that runs.
>

Exactly.

>
>  You mean that when one of the fibers started by the Scheduler is
starting other fibers they would usually await for them to finish, and that
is a blocking operating that blocks also the Scheduler?
>

When a *Fiber* from the *Scheduler* decides to create another *Fiber* and
then tries to call blocking functions inside it, control can no longer
return to the *Scheduler* from those functions.

Of course, it would be possible to track the state and disable the
concurrency mode flag when the user manually creates a *Fiber*. But… this
wouldn't lead to anything good. Not only would it complicate the code, but
it would also result in a mess with different behavior inside and outside
of *Fiber*.

This is even worse than calling *startScheduler*.

The hierarchical switching rule is a *design flaw* that happened
because a *low-level
component* was introduced into the language as part of the implementation
of a *higher-level component*. However, the high-level component is in
*User-land*, while the low-level component is in *PHP core*.

It's the same as implementing $this in OOP but requiring it to be
explicitly passed in every method. This would lead to inconsistent behavior.

So, this situation needs to be resolved one way or another.

--

Ed

Reply via email to