Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:102086 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 80959 invoked from network); 30 Apr 2018 10:35:24 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Apr 2018 10:35:24 -0000 Authentication-Results: pb1.pair.com smtp.mail=rasmus@mindplay.dk; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=rasmus@mindplay.dk; sender-id=unknown Received-SPF: error (pb1.pair.com: domain mindplay.dk from 209.85.220.182 cause and error) X-PHP-List-Original-Sender: rasmus@mindplay.dk X-Host-Fingerprint: 209.85.220.182 mail-qk0-f182.google.com Received: from [209.85.220.182] ([209.85.220.182:37131] helo=mail-qk0-f182.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 82/41-31220-661F6EA5 for ; Mon, 30 Apr 2018 06:35:19 -0400 Received: by mail-qk0-f182.google.com with SMTP id d74so6246755qkg.4 for ; Mon, 30 Apr 2018 03:35:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mindplay-dk.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=EPb+pjJYm7U8NL7c80IJfFZm0GqOn1jG5l1o2F7XdAQ=; b=kwdNqA4JakYrHM1hJmeUX5e1VM91mAnPdyrXIgptrZo3Z5Dm0COaBxQlEmEq797HC3 v/TiCbwAMJ/1YZ9FENirm2npnBCos+NPTEt640TyDq0O4uMjb0uzB1KH7L0cbnP+n/PH nUNolP2+LgfRaonGCy+8koKBrXLwztSehe0FHBxA5TgqfdC4n16XisB5dbf1gwdq5sGm i6VLtwNp+d7Fqos25fXgfV87JoLDI88xp6ypWa4P8s0vcNMUaNNtUnuyuT52KenkEkrY gox1Nr5COfCR7DTJlFGlwPmFvlKniU2N/8MewXss8a2ae3EFK1i+h2VOzomtc0PC/DqG io+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=EPb+pjJYm7U8NL7c80IJfFZm0GqOn1jG5l1o2F7XdAQ=; b=oIW98CeKQyxAU5YxFHhelsn55Nngsv/+XwdNMTYgvy5RLuGhUd8Hc6EYvX66b93seu tM81Ivv0/baCQ2p34KLyeqF0MADL01ACh0DQ6Q8VTrAp2Rtq4FLxGaUzSRqgGa0L41Wu AdhcbjY+4URaieuzas0xHtHJLpU4W/Si0RPY1z3gW9uOlwaNSJQIt48HlU5rdeqW+Ku2 Wvnz7PUHxymjixCi2CST+7ogtgww1pNikfz3OX7jqIUX8Ls1BNjkghsM5TyQIYody7Hu lu3ErUSCWHyDKsPwISRYWSLdOYC7F7wTnupnNeB4uid1GiuVtPSXwBPAmGuzM9w9Zfjk CHfg== X-Gm-Message-State: ALQs6tCTQaQK9mnIXAeN9q+tOwNtNO4NPxTVxa639GRFU0tAeEoeLwQA Gn8Jw7CKQwXkpsSBuhp3I2DqvknspDSvdhwMgx782+wbd2g= X-Google-Smtp-Source: AB8JxZonG7wQpka7K1Lpyc75BvDK5QYcS8nXv9Gol8baIoV9xsfGqtWNiSDcF1oaa9v5Kqg3QmhsQzwjAHNW+IZmM6I= X-Received: by 10.55.31.15 with SMTP id f15mr9929523qkf.421.1525084516457; Mon, 30 Apr 2018 03:35:16 -0700 (PDT) MIME-Version: 1.0 Received: by 10.237.45.35 with HTTP; Mon, 30 Apr 2018 03:35:15 -0700 (PDT) In-Reply-To: References: <76EBF900-3BE8-4B60-9422-880A9754FCC4@lvht.net> <0DDFDACA-6322-461C-9D57-215E8C7D9CD0@trowski.com> Date: Mon, 30 Apr 2018 12:35:15 +0200 Message-ID: To: Haitao Lv Cc: Niklas Keller , Aaron Piotrowski , PHP Internals , Dmitry Stogov Content-Type: multipart/alternative; boundary="001a1147a756db34c3056b0e683e" Subject: Re: [PHP-DEV] [RFC] Fiber support (again) From: rasmus@mindplay.dk (Rasmus Schultz) --001a1147a756db34c3056b0e683e Content-Type: text/plain; charset="UTF-8" >>>> - 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. I agree, two methods are probably not required. But I also agree with Aaron that the verb "resume" is confusing/misleading here - it implies something has already been running, which isn't the case when you initially create the Fiber. I'd suggest changing the name to start() - you can "start" something whether it's starting for the first time or starting again after a pause, but to "resume" something, it must have been already running, so it's a bit confusing. On Fri, Feb 9, 2018 at 1:12 AM, 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 of the stack should happen automatically, just like generators > > resize automatically. > > This size is the init stack size. It means when a Fiber created, it will > get a > dedicate stack of 4k size. When the fiber use all the stack space, zend vm > will > allocate additional space for feature call frame, automatically. > > The default size is 4k means that every fiber requires at least 4k memory > to use > as there own stack. But user can change this by php.ini and the construct > argument > to reduce the memory footprint. > > > > >> Fiber::yield cannot be used in internal callback > > > > This also seems problematic and will make fibers quite less useful, > > especially as these yields can happen anywhere down the stack. > > > > This do be a problem. But not so much big problem. > > You cannot use Fiber::yield like > > $f = new Fiber(function () { > array_map(function ($i) { > Fiber::yield($i); > }, [1, 2, 3]); > }); > $f->resume(); > $f->resume(); > > Because when zend execute the array_map, it will push a new frame onto the > c stack. > When zend execute Fiber::yield, it only backup it's php stack, and it's c > stack > will be overwrites. > > However, you can use Fiber::yield like > > $f = new Fiber(function () { > Fiber::yield(1); // will cause by resume, by an internal callback > }); > > ExtEventLoop::onRead($fd, function () { // this is an internal call > $f->resume(); > }); > > > Regards, Niklas > > > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > --001a1147a756db34c3056b0e683e--