Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126423 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 3758D1A00BC for ; Sun, 16 Feb 2025 11:41:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1739705906; bh=pmNfnOed4N5lVEUlEXL0q+5OXj7/5V5Mtqx/zIA7w9w=; h=Date:From:To:In-Reply-To:References:Subject:From; b=kwGp/DC7Y1ax97C+ZPbuOZko7Y1fzbRjecTR3Fdb0ups71VJJLHKZo080wXrinw7h j4egOYnrNp3hHN1DFdc3YjRUF2E6Dyiov76UxbET8pSHWq/dcu6z3bQ79DLMqpSsQH NCJng9pz5DA3qNido1CKCQE92bK0jjUHobfHexL24EnXof7dvWsvxjVln8TNeAaZJ1 K77E7mMlnLbK4iaEURY/iZTxjjeCmm6GYHEQ6JkzwcEYiijObB+BFX6YfIy+tnPtQv oza2uI1z061rSFHz3PkwK0FZOHa8LQ2JQ1GqOOHIlh/jLlDaGmYbNqUmvrkXmxSYh+ zM73l+eDZD/+Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 638FE180081 for ; Sun, 16 Feb 2025 11:38:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout-b7-smtp.messagingengine.com (fout-b7-smtp.messagingengine.com [202.12.124.150]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 16 Feb 2025 11:38:21 +0000 (UTC) Received: from phl-compute-13.internal (phl-compute-13.phl.internal [10.202.2.53]) by mailfout.stl.internal (Postfix) with ESMTP id 3F4A81140100 for ; Sun, 16 Feb 2025 06:41:02 -0500 (EST) Received: from phl-imap-09 ([10.202.2.99]) by phl-compute-13.internal (MEProxy); Sun, 16 Feb 2025 06:41:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1739706062; x=1739792462; bh=OqlJa61sr8 tqZsPUKxzo8rWSzKc3roLM0NUXLq/LfhM=; b=GuEHMwqFRB9nrcwGqccZz0RBT5 dAvHN6j2arMGCcrMCtiWn32KPJY2TJ2r7v45gEGmcqzmkAYQyUSRIQTvnRhd4pvQ eWgntcr0JgsT296dVa9o6fhs0SlZxRruHHfY8NsNWPWNoTHOuM5QSlyJ/Mgi1Q4R uaOiknCUWm0RwIalqAOK9LIq+eWTFCUHqn1gi4nVQWe05T2GihYwLFk2GkQuDg3h f5HSmQDW6BPDs5hC5CHyAEVeTiPXAdzt21qtKUTHNsxnNFESzAPtZIH87JZVWk+T Phz87zkamBT1JowwdB6+woEmLoBhlrmaai7UAbP4ooiGYb+OY0ydoU6fc5fg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1739706062; x=1739792462; bh=OqlJa61sr8tqZsPUKxzo8rWSzKc3roLM0NU XLq/LfhM=; b=rzEEvnn0jZLPzW4caP1tNY9svNrZo9YiZCmH/LHLFTJUXqKKSDv SWMJr6gxwKquuatQnB1+agzuVahgoW/PKxCdTnc0qavktMtDdkhPfGtCNN4NxgaG q6baWJNDaZxqVDJOWfpoJy0ol6xvmKUv6uiX6OLvYqTeIYQKq93EYDOFt1j7Ad+s jrQdKjsNvwaqB+J/GLWEwDGWolWL0ddwUAwkmunw0trHvMEgpEcX5PIrKjlPT1hz 8MM7kRE/InUzF8VTN2JnVcJJdkGzMINzMSNqG19wN4J65hF5M7XGsZmWdC1pp/2z mm3/OVTmEXqKhPsrnPnDCjy9kSeaJaQM00Q== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdehheefiecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecuogfuuhhsphgvtghtff homhgrihhnucdlgeelmdenucfjughrpefoggffhffvkfgjfhfutgesrgdtreerredtjeen ucfhrhhomhepfdftohgsucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurdgtoh guvghsqeenucggtffrrghtthgvrhhnpeekgeduhfdvtdevffekueehjefhudduhfduieeu ueetvddtudehkefffeetueehgfenucffohhmrghinhepghhithhhuhgsrdgtohhmpdefvh eglhdrohhrghenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhr ohhmpehrohgssegsohhtthhlvggurdgtohguvghspdhnsggprhgtphhtthhopedupdhmoh guvgepshhmthhpohhuthdprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhp hhhprdhnvght X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id B56B7780068; Sun, 16 Feb 2025 06:41:01 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Sun, 16 Feb 2025 12:40:41 +0100 To: internals@lists.php.net Message-ID: In-Reply-To: References: Subject: Re: [PHP-DEV] PHP True Async Content-Type: multipart/alternative; boundary=c210af0d81154495a43565570cc87223 From: rob@bottled.codes ("Rob Landers") --c210af0d81154495a43565570cc87223 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Fri, Feb 14, 2025, at 15:16, Edmond Dantes wrote: > Hello, *Jakub.* > (It seems that simply clicking "Reply" does not work for the conferenc= e) > ** > *> *I understand that's not ready for review yet but quickly > You could say that the code is in a state of "architectural stabilit= y," so it can be reviewed and criticized. (Unfortunately, only the Windo= ws build is currently working.)=20 > In the near future, I plan to start documenting the C-API, where I wil= l describe the implementation details in depth, but feel free to ask any= questions about this component. =20 >=20 > Link: https://github.com/EdmondDantes/php-src/tree/async/async >=20 Just looking through the PHP stubs, and here are some notes: Channels: - It is probably best to have channels be non-buffered by default (like = in Go); buffered channels can hide architectural issues in async code. - Why do we need "finishing" producing and consuming? Won't "closing" th= e channel be enough, or does closing a channel prevent consumers from re= ading pending items? Personally, it should be an exception (or at least = a warning) if a channel gets GC'd with pending data. - Looking at the public api, it seems that it is very hard to use correc= tly. It would probably be a good idea to pair it down and come up with a= n api/ideomatic usage that makes it hard to use incorrectly. Callback: - Can we name this Async\Closure or something similar? Just to keep it i= nline with the current \Closure - Speaking of, you probably meant to use \Closure as the $callback prope= rty instead of mixed? Futures: - The constructor for a Future is public, but it looks like it would be = weird to use. Module: - It would be nice to see this simply use Futures as much as possible. F= or example, returning a Future instead of FiberHandles. - Is onSignal OS signals or application signals? (I didn't look at the C= code) If the latter, it is probably better to use something other than = integer. If the former, this is usually handled by extensions (such as p= cntl) and comes with a ton of caveats. It might be better to let those e= xtensions handle that. Notifier: - Exposing $reserved -- which is accessible via reflection -- is probabl= y a bad idea. - Should this be implementing Stringable interface? Also, this will auto= matically cast to a string if accidentally passed to a function that tak= es a string -- unless you are using strict mode. https://3v4l.org/3AqcW = This is probably not desired. - Instead of Terminate(), should it be Close(), to be consistent with th= e rest of the library? - It would be nice to get a list of callbacks on the Notifier as well. Walker: - It would be nice to be able to get a future from the Walker instead of= polling "isFinished". - IMHO, it would be better to implement this around Futures (see amphp's= extensive library around this). Here are some examples from my own code: - timeouts: race two futures, one which times out and the other which pe= rforms a long-running task. If the timeout wins, then I cancel the long-= running task and proceed as an error. If the long-running task wins, I c= ancel the timeout. - wait for all to complete: there are a couple of variations on this the= me. But sometimes we want to wait for all to complete, errors or not; so= metimes we want to stop on the first error; and sometimes we want to jus= t get the first success (see timeouts). All in all, this is a good start. It would probably be a good idea to ta= ke a deeper look at other Channel implementations and borrow heavily fro= m them. The current implementation seems to leak a lot of internal infor= mation that most programs should not use. As a producer, all I care abou= t is that the channel is open; not that anyone is listening or not. Ther= e may be nobody listening right now; but because it is async, it is my j= ob as a programmer to make sure that someone is listening, eventually. S= ame with consumers, they don't need to know whether someone is actually = producing, just that the channel is open so they can consume. It may be = a good idea to create a way to use it with match: $result =3D match (Async\select($channel)) { Async\EOF =3D> "channel closed", default =3D> $channel->receive(), } Where Async\select() just pauses until there is a value and returns "nul= l" or "EOF" or something when it has a value available or becomes closed= . Also, keep in mind this is pretty valid: $channel->send($data); $channel->close(); A consumer should read $data before seeing the channel as closed. I pres= ume that this is what "finishProducing()" is for, but it requires synchr= onization to work properly and the entire idea of channels is to not nee= d synchronization at all. =E2=80=94 Rob --c210af0d81154495a43565570cc87223 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable
On Fri, Feb 14,= 2025, at 15:16, Edmond Dantes wrote:
Hello, Jakub.
(
It seems that simply c= licking "Reply" does not work for the conference)
=
I u= nderstand that's not ready for review yet but quickly
  You could say that the code is in a state of "architectural st= ability," so it can be reviewed and criticized. (Unfortunately, only the= Windows build is currently working.) 
In the near fu= ture, I plan to start documenting the C-API, where I will describe the i= mplementation details in depth, but feel free to ask any questions about= this component.  



J= ust looking through the PHP stubs, and here are some notes:

Channels:
- It is probably best to have c= hannels be non-buffered by default (like in Go); buffered channels can h= ide architectural issues in async code.
- Why do we need "= finishing" producing and consuming? Won't "closing" the channel be enoug= h, or does closing a channel prevent consumers from reading pending item= s? Personally, it should be an exception (or at least a warning) if a ch= annel gets GC'd with pending data.
- Looking at the public= api, it seems that it is very hard to use correctly. It would probably = be a good idea to pair it down and come up with an api/ideomatic usage t= hat makes it hard to use incorrectly.

Callb= ack:
- Can we name this Async\Closure or something similar= ? Just to keep it inline with the current \Closure
- Speak= ing of, you probably meant to use \Closure as the $callback property ins= tead of mixed?

Futures:
- The= constructor for a Future is public, but it looks like it would be weird= to use.

Module:
- It would b= e nice to see this simply use Futures as much as possible. For example, = returning a Future instead of FiberHandles.
- Is onSignal = OS signals or application signals? (I didn't look at the C code) If the = latter, it is probably better to use something other than integer. If th= e former, this is usually handled by extensions (such as pcntl) and come= s with a ton of caveats. It might be better to let those extensions hand= le that.

Notifier:
- Exposing= $reserved -- which is accessible via reflection -- is probably a bad id= ea.
- Should this be implementing Stringable interface? Al= so, this will automatically cast to a string if accidentally passed to a= function that takes a string -- unless you are using strict mode. = https://3v4l.org/3AqcW This = is probably not desired.
- Instead of Terminate(), should = it be Close(), to be consistent with the rest of the library?
<= div>- It would be nice to get a list of callbacks on the Notifier as wel= l.

Walker:
- It would be nice= to be able to get a future from the Walker instead of polling "isFinish= ed".
- IMHO, it would be better to implement this around F= utures (see amphp's extensive library around this). Here are some exampl= es from my own code:

- timeouts: race two f= utures, one which times out and the other which performs a long-running = task. If the timeout wins, then I cancel the long-running task and proce= ed as an error. If the long-running task wins, I cancel the timeout.
=

- wait for all to complete: there are a couple= of variations on this theme. But sometimes we want to wait for all to c= omplete, errors or not; sometimes we want to stop on the first error; an= d sometimes we want to just get the first success (see timeouts).

All in all, this is a good start. It would probab= ly be a good idea to take a deeper look at other Channel implementations= and borrow heavily from them. The current implementation seems to leak = a lot of internal information that most programs should not use. As a pr= oducer, all I care about is that the channel is open; not that anyone is= listening or not. There may be nobody listening right now; but because = it is async, it is my job as a programmer to make sure that someone is l= istening, eventually. Same with consumers, they don't need to know wheth= er someone is actually producing, just that the channel is open so they = can consume. It may be a good idea to create a way to use it with match:=

$result =3D match (Async\select($channel))= {
  Async\EOF =3D> "channel closed",
  default =3D> $channel->receive(),
}

Where Async\select() just pauses until there is a = value and returns "null" or "EOF" or something when it has a value avail= able or becomes closed. Also, keep in mind this is pretty valid:

$channel->send($data);
$channel-&= gt;close();

A consumer should read $data be= fore seeing the channel as closed. I presume that this is what "finishPr= oducing()" is for, but it requires synchronization to work properly and = the entire idea of channels is to not need synchronization at all.

=E2=80=94 Rob
--c210af0d81154495a43565570cc87223--