Re: [PHP-DEV] [RFC] Fiber support (again)

2018-02-10 Thread Niklas Keller
>> There would also need to be something that stops the script execution
>> as soon as there's no non-suspended Fiber anymore.
>
> As you pointed out, the main process cannot be a Fiber because it need to
> schedule other fibers.

The conclusion is wrong. There just needs to be a way to access this
fiber, e.g. Fiber::getMain().

>>
>> Regarding the internal calls: A core dump / segfault in case of
>> Fiber::yield() inside an internal function is unacceptable. It doesn't
>> give the user any clue what's wrong. Instead, an exception could be
>> thrown from Fiber::yield(), which just bubbles up then. Full support
>> for internal functions could be added at a later point then.
>
> It is impossible to solve this issue before we get a pure stackless Zend VM.
>
> If this feature can be merged into PHP 7.3, we could introduce a new counter
> to record the zend vm nested level. Every time you enter an internal call,
> let zend increment the counter, and decrement it when out.
>
> When we create a fiber, we remember current vm nested level. When zend execute
> Fiber::yield,it will throw an error if the current vm nested level is not
> equal to the original one.
>
> This feature cannot be implemented without changing the zend vm code base.

You're proposing this as language feature, not as an external
extension, so that is entirely fine and actually the reason why this
should be in core instead of an external extension.

Regards, Niklas

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Fiber support (again)

2018-02-10 Thread 吕海涛


> On Feb 10, 2018, at 22:49, Niklas Keller  wrote:
> 
>> Hi, all,
>> 
>> I have updated the RFC https://wiki.php.net/rfc/fiber
>> 
>> changes list:
>> 
>> - introduce the `throw(Exception $exceptin)` API
>> - record issues discussed
> 
> What about my suggestion of making PHP's main() automatically a Fiber,
> which avoids Fiber::yield() being used outside of a Fiber, because
> everything is a Fiber?
> 
> This would require another continuation mechanism, as nothing has
> access to the automatically created main()-Fiber otherwise.
> 
> There would also need to be something that stops the script execution
> as soon as there's no non-suspended Fiber anymore.

As you pointed out, the main process cannot be a Fiber because it need to
schedule other fibers. 

> 
> Regarding the internal calls: A core dump / segfault in case of
> Fiber::yield() inside an internal function is unacceptable. It doesn't
> give the user any clue what's wrong. Instead, an exception could be
> thrown from Fiber::yield(), which just bubbles up then. Full support
> for internal functions could be added at a later point then.

It is impossible to solve this issue before we get a pure stackless Zend VM.

If this feature can be merged into PHP 7.3, we could introduce a new counter
to record the zend vm nested level. Every time you enter an internal call,
let zend increment the counter, and decrement it when out. 

When we create a fiber, we remember current vm nested level. When zend execute
Fiber::yield,it will throw an error if the current vm nested level is not
equal to the original one.

This feature cannot be implemented without changing the zend vm code base.

Maybe we could get a stackless zend vm in the feature. like the stackless python

https://github.com/stackless-dev/stackless

> 
> Regards, Niklas




--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Fiber support (again)

2018-02-10 Thread Niklas Keller
> Hi, all,
>
> I have updated the RFC https://wiki.php.net/rfc/fiber
>
> changes list:
>
> - introduce the `throw(Exception $exceptin)` API
> - record issues discussed

What about my suggestion of making PHP's main() automatically a Fiber,
which avoids Fiber::yield() being used outside of a Fiber, because
everything is a Fiber?

This would require another continuation mechanism, as nothing has
access to the automatically created main()-Fiber otherwise.

There would also need to be something that stops the script execution
as soon as there's no non-suspended Fiber anymore.

Regarding the internal calls: A core dump / segfault in case of
Fiber::yield() inside an internal function is unacceptable. It doesn't
give the user any clue what's wrong. Instead, an exception could be
thrown from Fiber::yield(), which just bubbles up then. Full support
for internal functions could be added at a later point then.

Regards, Niklas


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Fiber support (again)

2018-02-10 Thread Haitao Lv
Hi, all,

I have updated the RFC https://wiki.php.net/rfc/fiber

changes list:

- introduce the `throw(Exception $exceptin)` API
- record issues discussed

> On Feb 9, 2018, at 08:12, Haitao Lv  wrote:
> 
>> 
>> On Feb 9, 2018, at 06:22, Niklas Keller  wrote:
>> 
>>> 
 - How do you determine when a fiber has returned? Looking at the source,
>>> it appears Fiber::status() must be used, comparing against constants.
>>> Separate methods similar to Generator would be better IMO. e.g.:
>>> Fiber::alive(), Fiber::suspended(), Fiber::running()
>>> 
>>> Offering methods like Fiber::alive, Fiber::running makes no difference to
>>> check the Fiber::status() return value. This is just a style issue. And as
>>> a language feature,
>>> Fiber only offer the essential API and let other works to the user land.
>> 
>> 
>> The language should offer a sane API, not the absolute minimum required to
>> work for these things.
> 
> The Ruby's Fiber do offer a live? method but does not have a getStatus method.
> The Lua's coroutine only offer a status method.
> 
> So do we really need to offer three additional helper method? Or what is your
> advice about these API?
> 
>> 
 - What about throwing exceptions into a fiber?
>>> 
>>> Currently does not support throw exception into the fiber. User land code
>>> could check
>>> the value of Fiber::yield and throw exception themselves. The Ruby's Fiber
>>> and Lua's
>>> coroutine also does not support such api as well.
>> 
>> 
>> And throw the exception where? That means async code with fibers can't
>> really handle errors?
> 
> Actually you can transfer any thing to Fiber by the resume method. And you can
> check the return value of Fiber::yield to handle error.
> 
> Fiber is designed as a primitive, low level, and lightweight feature. User 
> land
> code seldom not need to use them directly in your normal code.
> So the following is not a big problem,
> 
> $a = Fiber::yield(...);
> if ($a === false) {
>   throw new Exception(...);
> }
> 
> And both the Ruby and Lua does not offer such API as well.
>> 
>>> 
 
 - Using Fiber::resume() to initialize the fiber and resume feels
>>> awkward. Separate methods again would be better here, perhaps
>>> Fiber::init(...$args) and Fiber::resume($send).
>>> 
>>> All Fiber created with a suspended status. So make resume to do both the
>>> init and resume
>>> do make sense.
>>> 
>> 
>> It does't make sense to me. Reading the example in the README and
>> understanding why the first resume() takes two arguments instead of one
>> took me quite some minutes.
> 
> This Ruby's Fiber and Lua's coroutine using one resume API to init and resume
> the coroutine. I do not think a dedicate is really required.
> 
> The generator cannot be init by it's send method. And if you want to implement
> coroutine feature(without stack) by it, you have to write code
> 
> function run() {
>if ($this->beforeFirstYield) {
>$this->beforeFirstYield = false;
>return $this->coroutine->current();
>} else {
>$retval = $this->coroutine->send($this->sendValue);
>$this->sendValue = null;
>return $retval;  
>}   
> }
> 
> It is verbose.
> 
> See 
> https://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html
> 
>> 
>>> Please see Ruby Fiber API https://ruby-doc.org/core-2.2.0/Fiber.html.
>>> 
 
 - What happens if the sub1() function in the RFC is invoked outside of a
>>> fiber?
>>> 
>>> You will get a Fatal Error like
>>> Fatal error: Uncaught Error: Cannot call Fiber::yield out of Fiber
>>> 
 - I think a keyword here would be beneficial, even if it has a minor BC
>>> impact. Fibers could then be written like generators. `await` or `emit` as
>>> a keyword perhaps? This would be a less verbose API, feel less magical (a
>>> static method call that actually pauses execution feels out of place), and
>>> would allow Fibers to be returned from methods, named functions, etc with
>>> less boilerplate.
>>> 
>>> Wishing this to be accepted by the community in the PHP 7.3, so no keyword
>>> is accepted.
>>> And if the community cannot accept, the Fiber can be still distributed as
>>> a standalone
>>> extension. So we cannot depend on a new keyword.
>> 
>> 
>> Right, if it's a standalone extension it can't use a new keyword, but as a
>> language feature it totally can.
> 
> In my opinion, using a keyword or call a method is just a coding style 
> problem.
> Introducing a new keyword does not offer any benefit by makes a minor BC.
> 
> Both Ruby's Fiber and Lua's coroutine does not required a dedicate keyword.
> 
>> Looking at the current README, there are two issues that must be completely
>> solved IMO before accepting this:
>> 
>>> Each Fiber has a separate 4k stack. You can use the fiber.stack_size ini
>> option to change the default stack size. You can also use the second
>> argument of Fiber::__construct to set the stack size on fly.
>> 
>> Resizing