Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126585 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 B24091A00BC for ; Wed, 5 Mar 2025 21:10:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741208872; bh=6d3vyEuefd3bDJ/ulBvOURJmUZP0EkCmBZVIl8Yz1wk=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=JXdJhyeEYj4sPOzpTYlqyVljmv9FR3rYMjYlo+eR932muNIvUcjRfnLhP6JuR3SxW sQ8Tw38VrDq0vgJOzVq+smE/KmZfhPPaOEguZt3vuQMgwQ7R/U3qk3CXvJApnagbTZ qLkbqL5l52P4dZosiN9UL6DiuPgtF3P6eO/BcA/fwaLIsS/v7NFHITOwVfB4nMUtac lBETxn0pal7vhMXgpTKSOqbbKsMzjZk2aXLraL/wG+oGHBlssm5XKxRtVZJ7mzrX9n 8Mu7oDrNJworK907Td1o4zreFE2OJA0KbA71FhXSKK37fenmaNuNdjUi2YAQDQQTNV zZ+NMxBpzJ6Kw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6884F180082 for ; Wed, 5 Mar 2025 21:07:51 +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=-3.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f170.google.com (mail-yb1-f170.google.com [209.85.219.170]) (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 ; Wed, 5 Mar 2025 21:07:51 +0000 (UTC) Received: by mail-yb1-f170.google.com with SMTP id 3f1490d57ef6-e5372a2fbddso5265046276.3 for ; Wed, 05 Mar 2025 13:10:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741209026; x=1741813826; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=FpQuAaW3lOD2MwqzDXeHTFs0QihrW3C3iROwGwHGR6g=; b=CnHr1lyCEqPTFCI7h61zFOzvYqz0iivEGZcLZ/uosqPZ3fEEcsFTfrZyptyGDA9YJs KzXhfdDurQ2Kb380XxvsguACYBivEPev8wh78T7FNXCUZ22c4h4ys0aUdbZeaISlKoqf rj2GAITn6c3NlWiH/Eggx29GrzhIUUvDBRBQor2ZoInTkFMk/8iTqJDUM4NMNNqvGqno ritWj66WUzx6LJVWB9X0uOdSlaTJNL0/tzL/dgcVx3Ee2hbe2lMDaOaNhpfgnkJ/SVhh JHz3P6oG6X7gFHPBbFdX7KyPQOdEbGhxFMLFwkXqL9woGn8zQYSjWnjKTVvAvwuUs7f2 NghA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741209026; x=1741813826; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=FpQuAaW3lOD2MwqzDXeHTFs0QihrW3C3iROwGwHGR6g=; b=YNhusLy7Ypn0tzmtlzIEE3HUY4+WbFnD/mjG5fQuwWlJYCfVwtSxCYlBoxdS2aLB+P u7GEFO3zY+Ii+KR/7KnzU5mka9q78X82eSBGRg+glwtbBv1H38YY9FMGBkOSNwxxEwXR /nQdSk7Grhqalw9xhHMouJ9Q7I8wGnKuQ79DgHIioCl/V4MdxoluyHJdcWrSua4TWMlJ 6P0BoIeYxNXPHq/Seljha4v0i1GByYN5UdCD65rLU1aAX+7iIE+6n0BuwgC4SegmfZja LPHREBH1eTx6cDe7aYNA7/yQh7Y8l+eF7nmeJzieoklhXpMfBP9iYgWHM0QPbLBzUqpa yPjQ== X-Gm-Message-State: AOJu0YxOZnqaogAit3bjyJvQh7VovwX8BtAuzsSxUtlp4m7Tmn+A4ITJ Qjh7yl/HDUorM2v7jbDVZ9m//oevCjV9U9j2HrxUi72jsP2BGA09ZwWRT7On0wYZEm5sme4VUgo ISup+YaJpUpnqXeIDbud0UghjllOHxxkpBUc= X-Gm-Gg: ASbGnctnylbwzGe7NZZFWxr61plrFZUpFMOWn+B3wv2cOY7KcR7SL0neKaW48uhPRrB mN5OmZKx1hgJYoKdITBlQ48ZYlhK9XiEkHGAMZKSyfkrWVppXYMEvXiO2bF3O8BH1EQHTvB6KWL 1QdLOSgpOEjeprxEXBQUoninmrhw== X-Google-Smtp-Source: AGHT+IFfPH2n91jCZCwXDUWfcyAJmeZ4f6WK3hrgNHtfa9AA6spF0oNubsVZCVTIamgcMf5Ehqg1in+lZTGvTm1YXNk= X-Received: by 2002:a05:690c:4c09:b0:6f9:525d:a096 with SMTP id 00721157ae682-6fda3031ceamr71342657b3.3.1741209026166; Wed, 05 Mar 2025 13:10:26 -0800 (PST) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <9964db8c-0ffe-43d5-8246-47fc76b07180@app.fastmail.com> <78a03dd0-fd4a-4f4a-ad8a-37e5704f06fc@app.fastmail.com> In-Reply-To: <78a03dd0-fd4a-4f4a-ad8a-37e5704f06fc@app.fastmail.com> Date: Wed, 5 Mar 2025 23:10:15 +0200 X-Gm-Features: AQ5f1Jr1rQ668W5pPvuLmBRMhCnw3q_MByqZcmN9EOuK1PM8yxCwX1j3ng8PDcI Message-ID: Subject: Re: [PHP-DEV] PHP True Async RFC To: Larry Garfield Cc: php internals Content-Type: multipart/alternative; boundary="0000000000007c0d4b062f9ed1cc" From: edmond.ht@gmail.com (Edmond Dantes) --0000000000007c0d4b062f9ed1cc Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable > > Thinking aloud, perhaps we could cause `new Fiber` to create an automatic async block? > The main issue with Fibers is their switching logic: If you create Fiber A and call another Fiber B inside it, Fiber B can only return to the Fiber that created it, not just anywhere. However, the Scheduler requires entirely different behavior. This creates a conflict with the Scheduler. Moreover, it can even break the Scheduler if it operates based on Fibers. That's why all these strange solutions in the RFC are just workarounds to somehow bypass this problem. But it seems we've already found an alternative solution. > I cannot speak for Derick. Of course, I just mean that he probably won't be happy about it :) > No, just those functions/objects that necessarily involve running async control commands. Most wouldn't. > They would just silently context switch when they hit an IO operation (which as noted above is transparency supported, which is what makes this > work) and otherwise behave the same. So it's something more like Go or Python. > > $val =3D async(function(AsyncContext $ctx) use ($stuff, $fn) { > $result =3D []; > foreach ($stuff as $item) { > $result[] =3D $ctx->run($fn); >} > > // We block/wait here until all subtasks are complete, then the async() call returns this value. > return $result; > }); Do I understand correctly that at the point $val =3D async(function(AsyncContext $ctx) use ($stuff, $fn) execution stops until everything inside is completed? If so, let me introduce a second semantic option (for now, I'll remove the context and focus only on the function). ```php $url1 =3D 'https://domain1.com/'; $url2 =3D 'https://domain2.com/'; $url_handle =3D fn(string $url) =3D> file_get_contents($url); $res =3D Async\start(function() use ($url1, $url2, $url_handle) { $res1 =3D Async\run($url_handle, $url1); $res2 =3D Async\run($url_handle, $url2); Async\run(fn() =3D> sleep(5)); // some logic here return $merged_result; }); ``` What's Happening Here: 1. After calling $res =3D Async\start(), the code waits until the entire block completes. 2. Inside Async\start, the code waits for all nested coroutines to finish. 3. If a coroutine has other nested coroutines, the same rule applies. Rules Inside an Asynchronous Block: 1. I/O functions do not block coroutines within the block. 2. Creating a new Fiber is not allowed =E2=80=94 an exception will be th= rown: you cannot use Fiber. 3. Unhandled exceptions will be thrown at the point of $res =3D Async\start(). Coroutine Cancellation Rules: Canceling a coroutine cancels it and all its child coroutines (this cannot be bypassed unless the coroutine is created in a different context). How does this option sound to you? Essentially, this is Kotlin, but it should also resemble Python. However, unlike Kotlin, there are no special language constructs here=E2=80=94code b= locks naturally serve that role. Of course, syntactic sugar can be added later for better readability. And if you like this, I have good news: there are no implementation issues at this level. In terms of semantic elegance, the only thing that bothers me is that retur= n behavior is slightly altered =E2=80=94 meaning the actual "return" won=E2= =80=99t happen until all child functions complete. This isn=E2=80=99t very good, and Kotli= n=E2=80=99s style would fit better here. But on the other hand =E2=80=94 can we live with this? > I cannot speak to JS Symbols as I haven't used them. > I am just vhemently opposed to globals, no matter how many layers they're wrapped in. :-) Most uses could be replaced by proper DI or partial application. You won=E2=80=99t be able to use DI because you have only *one service (ins= tance of class)* for the entire application, not a separate service for each coroutine. This service is shared across the application and can be called from any coroutine. As a result, the service needs memory slots to store or retrieve data. DI is a mechanism used once during service initialization, not every time a method is called. The only question is whether to use open text keys in the context, which is unsafe and can lead to collisions, or to use a unique key-object that is known only to the one who created it. (If PHP introduces object constants, this syntax would also look elegant.) There is, of course, another approach: making Context any arbitrary object defined by the user. But this solution has a known downside =E2=80=94 lack = of a standard interface. > (Or even just $ch->inPipe and $ch->outPipe, now that we have nice property support.) Just a brilliant idea. :) Have a good day! Ed. --0000000000007c0d4b062f9ed1cc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
>=C2=A0
>=C2=A0 Thinking aloud, perhaps we could cause `new Fiber` to create an automatic a= sync block?
>

The main issue with Fibers is their switching= logic:
If you create Fiber A and call another Fiber B inside it, Fiber = B can only return to the Fiber that created it, not just anywhere. However,= the Scheduler requires entirely different behavior.

This creates a c= onflict with the Scheduler. Moreover, it can even break the Scheduler if it= operates based on Fibers. That's why all these strange solutions in th= e RFC are just workarounds to somehow bypass this problem. But it seems we&= #39;ve already found an alternative solution.

> I cannot speak for= Derick.

Of course, I just mean that he probably won't be happy about it :)=C2= =A0

> No, just those functions/objects that necessarily involve ru= nning async control commands.=C2=A0 Most wouldn't.=C2=A0
> They = would just silently context switch when they hit an IO operation (which as = noted above is transparency supported, which is what makes this
> wo= rk) and otherwise behave the same.=C2=A0

So it's something more = like Go or Python.

>
>=C2=A0 $val =3D async(function(AsyncContext $ctx) use ($stuff, $fn) {
>=C2= =A0 $result =3D [];
>=C2=A0 foreach ($stuff as $item) {
>=C2=A0= =C2=A0$result[] =3D $ctx->run($fn);
>}
>
>=C2=A0 // W= e block/wait here until all subtasks are complete, then the async() call re= turns this value.
>=C2=A0 return $result;
> });

Do I und= erstand correctly that at the point $val =3D async(function(AsyncCont= ext $ctx) use ($stuff, $fn) execution stops until everything inside = is completed?

If so, let me introduce a second semantic option (for n= ow, I'll remove the context and focus only on the function).=C2=A0=C2= =A0

```php
$url1 =3D 'https:/= /domain1.com/';
$url2 =3D '= https://domain2.com/';

$url_handle =3D fn(string $url) =3D&g= t; file_get_contents($url);

$res =3D Async\start(function() use ($ur= l1, $url2, $url_handle) {
=C2=A0 =C2=A0 $res1 =3D Async\run($url_handle,= $url1);
=C2=A0 =C2=A0 $res2 =3D Async\run($url_handle, $url2);

= =C2=A0 =C2=A0 Async\run(fn() =3D> sleep(5));

=C2=A0 =C2=A0 // som= e logic here

=C2=A0 =C2=A0 return $merged_result;
});
```
<= /p>

What's Happening Here:

  1. After calling $res =3D = Async\start(), the code waits until the entire block completes.
  2. =
  3. Inside Async\start, the code waits for all nested coroutin= es to finish.
  4. If a coroutine has other nested coroutines, the same = rule applies.

Rules Inside an Asynchronous Block:

  1. = I/O functions do not block coroutines within the block.
  2. Creating a = new Fiber is not allowed =E2=80=94 an exception will be thrown= : you cannot use Fiber.
  3. Unhandled exceptions will be t= hrown at the point of $res =3D Async\start().

Cor= outine Cancellation Rules:

Canceling a coroutine cancels it and all = its child coroutines (this cannot be bypassed unless the coroutine is creat= ed in a different context).

How does this option sound to you?

= Essentially, this is Kotlin, but it should also resemble Python. However, u= nlike Kotlin, there are no special language constructs here=E2=80=94code bl= ocks naturally serve that role. Of course, syntactic sugar can be added lat= er for better readability.=C2=A0=C2=A0

And if you like this, I have g= ood news: there are no implementation issues at this level.

In terms = of semantic elegance, the only thing that bothers me is that return behavior is slightly altered =E2=80=94 meaning the actual "retur= n" won=E2=80=99t happen until all child functions complete. This isn= =E2=80=99t very good, and Kotlin=E2=80=99s style would fit better here.

=

But on the other hand =E2=80=94 can we live with this?

> I cann= ot speak to JS Symbols as I haven't used them.=C2=A0
> I am just= vhemently opposed to globals, no matter how many layers they're wrappe= d in. :-)=C2=A0 Most uses could be replaced by proper DI or partial applica= tion.

You won=E2=80=99t be able to use DI because you have only on= e service (instance of class)=C2=A0for the entire application, not a se= parate service for each coroutine. This service is shared across the applic= ation and can be called from any coroutine. As a result, the service needs = memory slots to store or retrieve data. DI is a mechanism used once during = service initialization, not every time a method is called.

The only q= uestion is whether to use open text keys in the context, which is unsafe an= d can lead to collisions, or to use a unique key-object that is known only = to the one who created it. (If PHP introduces object constants, this syntax= would also look elegant.)

There is, of course, another approach: mak= ing Context any arbitrary object defined by the user. But this= solution has a known downside =E2=80=94 lack of a standard interface.

<= p>> (Or even just $ch->inPipe and $ch->outPipe, now that we have n= ice property support.)

Just a brilliant idea. :)

Have a good da= y!

Ed.=C2=A0=C2=A0

--0000000000007c0d4b062f9ed1cc--