Re: add Fiber (sackful coroutine) support
| From: | Haitao Lv | Date: | Fri, 01 Sep 2017 13:02:29 +0000 |
| Subject: | Re: add Fiber (sackful coroutine) support | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-100343@lists.php.net to get a copy of this message | ||
> On 1 Sep 2017, at 20:45, Rowan Collins <rowan.collins@gmail.com> wrote:
>
> Is this your own invention, or is the name and semantics based on some existing language or
> computer science theory? "Fiber" makes me think of strings, rather than coroutines, so
> maybe I'm missing a key metaphor here.
Fiber is a lightweight thread. Please see https://en.wikipedia.org/wiki/Fiber_(computer_science)
And ruby support Fiber. Please see https://ruby-doc.org/core-2.4.1/Fiber.html
>
>>> <?php
>>> function foo($a)
>>> {
>>> $b = await $a + 1;
>>> echo $b;
>>> }
>
> Should "await" be "yield" here? If not, what happens if I call foo()
> without being inside a Fiber?
No. A function with a yield will always return a Generator object. A fiber with await will return
any
value. You can see the await as a resumable return. The value after it will be returned and the
function
will be paused.
>
> Similarly, if I run bar() and it runs foo(), what result will I get outside a Fiber, since
> bar() has no yield, so is not itself a generator?
>
>
>> So the Fiber API is a little like the Generator API, but is more simple
>> yet powerful. So there
>> is no need to distinct $generator->current(), $generator->send(), and
>> $generator->getReturn().
>
> Your ->resume() doesn't seem to do anything a normal generator can't, except that
> the yield is nested deeper.
The await is a nested deeper yield!
> Nor does it seem to replace getReturn().
<?php
$f = new Fiber(function ($a) {
return 1;
});
echo $f->resume(); // will output 1
> Meanwhile, how does this relate to other ways of combining generators, such as "yield
> from"?
You can use Fiber to implement a more simple generator, because fiber can be paused/resumed in its
deeper
call.
<?php
function bar()
{
foreach ([5,6] as $i) {
await $i;
}
}
function foo()
{
foreach ([3,4] as $i) {
await $i;
}
bar();
}
$f = new Fiber(function ($a) {
await 1;
foo();
});
echo $f->resume(); // will output 1
echo $f->resume(); // will output 2
echo $f->resume(); // will output 3
echo $f->resume(); // will output 4
echo $f->resume(); // will output 5
echo $f->resume(); // will output 6