Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112818 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 60469 invoked from network); 8 Jan 2021 21:10:14 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 8 Jan 2021 21:10:14 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 60F9C1804CF for ; Fri, 8 Jan 2021 12:47:16 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mercury.negativeion.net (mercury.negativeion.net [199.38.81.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 8 Jan 2021 12:47:15 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by mercury.negativeion.net (Postfix) with ESMTP id 1987920BFDD9AB; Fri, 8 Jan 2021 15:47:15 -0500 (EST) Received: from mercury.negativeion.net ([127.0.0.1]) by localhost (mercury.negativeion.net [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9E7Ixk1gROzf; Fri, 8 Jan 2021 15:47:14 -0500 (EST) Received: from [10.0.1.101] (unknown [173.225.146.47]) by mercury.negativeion.net (Postfix) with ESMTPSA id 0430920BFDD99C; Fri, 8 Jan 2021 15:47:13 -0500 (EST) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.1\)) In-Reply-To: Date: Fri, 8 Jan 2021 14:47:13 -0600 Cc: php internals Content-Transfer-Encoding: quoted-printable Message-ID: <684A6C8C-59EE-4187-AAFC-AB20622F8309@trowski.com> References: To: Peter Stalman X-Mailer: Apple Mail (2.3608.120.23.2.1) Subject: Re: [PHP-DEV] [RFC] Fibers From: aaron@trowski.com (Aaron Piotrowski) Hi Peter, > On Jan 8, 2021, at 3:03 AM, Peter Stalman wrote: >=20 > I've been playing around with this for a bit, and I have some more = questions. I see you recently changed how the `FiberScheduler` works, = making it `final` and adding some "is" functions to match it more to a = regular fiber. >=20 > Since the `FiberScheduler` is itself also a fiber, why does it need to = be a separate class? Why did you choose to go this way and make it = "special" instead of not just making a regular fiber into a scheduler in = userland. =20 `FiberScheduler` is =E2=80=9Cspecial=E2=80=9D because user code is not = in control of suspending/resuming the underlying fiber, so = `FiberScheduler` is a different class from `Fiber` without those = methods. Internally a user fiber and scheduler fiber are similar, but I = wanted to differentiate them in user code. `FiberScheduler` recently changed from an interface to a class because = we discovered that automatically creating a scheduler fiber internally = would make it difficult for adaptors or wrappers of a `FiberScheduler` = to not create multiple internal scheduler fibers when there should only = be a single scheduler fiber. The API largely works the same, but now the = creation of the scheduler fiber is explicit in user code instead of done = internally. This way adaptors or wrappers can return a single = `FiberScheduler` instance. More code is required in user libraries, but = offers greater flexibility. > Could you have two or more schedulers? You can have two or more schedulers in a single script. Only one can = ever be running at a single time. > Could you get by without a scheduler and call a fiber inside a fiber = recursively? This design requires a scheduler fiber to be entered between suspending = one user fiber and resume another user fiber. User fibers are designed = to be independent. If two users fibers need to communicate, they should = use something similar to Go=E2=80=99s channels to exchange data. >=20 > Related to that, I noticed it was not possible to call `Fiber::this()` = from within the scheduler, why is that? Is it not just another fiber? = Or is this to prevent it from being passed to another scheduler? A scheduler fiber cannot be suspended or resumed by user code so it is = not useful to get a reference to that fiber. >=20 > Alternatively, going the other way, instead of making the scheduler a = unique class that needs to be passed around, why not go the more = "traditional" PHP route and pattern it after = `register_shutdown_function(callable $callback, mixed ...$args) : void`, = `spl_autoload_register(callable $autoload_function =3D ?, bool $throw =3D = true, bool $prepend =3D false) : bool`, and those type of functions? = After all, isn't it just a callback too? Something like = `register_fiber_scheduler(callable $callback) : void`? >=20 > This would remove the need for a special scheduler class and the need = for passing the scheduler back to the `Fiber::suspend()`. Each = `suspend()` call would bubble up through the registered scheduler = callbacks. This would allow competing schedulers to work nicer = together, instead of one scheduler having to finish before the higher up = scheduler can run it's next loop. The scheduler to be entered is specific to the code calling = `Fiber::suspend()`. Registering a global scheduler would require only a = single scheduler to be used in a script. Only a single scheduler is = entered on a call to `Fiber::suspend()`, not multiple schedulers. = Registering schedulers or wrapping application code in boilerplate = depending on the library being used is something this API is attempting = to avoid. >=20 > Either way, doesn't the fiber already know which scheduler it is in = when it suspends? No, a fiber can potentially use different schedulers at different = suspend points. The scheduler that starts a fiber does not necessarily = need to be the only scheduler that suspends the fiber. Hopefully that helps in understanding how the API works. Please take a = look at how amphp v3 uses fibers in these examples = https://github.com/amphp/amp/tree/v3/examples/pipeline or in react-fiber = https://github.com/trowski/react-fiber/tree/master/examples where the = Fiber API is handled by the library rather than =E2=80=9Capplication=E2=80= =9D code. Cheers, Aaron Piotrowski