Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129926 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 lists.php.net (Postfix) with ESMTPS id EB3811A00BC for ; Mon, 26 Jan 2026 08:23:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1769415794; bh=9ZSlQwx9CXjQmpYhlKZ/dVzxFvZeOQl01QhLt8ptdsk=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=HP60qLdlXuMYcJkjsFJei01/Fl+PxHt8rYrpO9uxX/jyY0Zkbj4EraOd1QYHLDRvN OYv8lCDcSTzEq2B6OAk4YNXlSNhLlSDigcai09r0DXipMt3jVjv/wRNpN/SZMCB57f Xp9DfwzPkmjxWCgFAO3FKrc7M9Bolg4WRIMM5TzvJu3dKcHjC43ywRpZusaP0MBmj7 xCDUv5Mtf3rtXSTltRvWc/zPc1GTdZE/46YDfpLF9UJ3g6mPEMwxxGEXqqVrIBLndI Ab4spkIekKaupUWLkFxMIjp1nBQlxjHtty96/bhSLhGT50/RkG3bc42wFzl25rZwso VT0jpMOkeu3Jg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A951E18002F for ; Mon, 26 Jan 2026 08:23:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-vs1-f53.google.com (mail-vs1-f53.google.com [209.85.217.53]) (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 ; Mon, 26 Jan 2026 08:23:13 +0000 (UTC) Received: by mail-vs1-f53.google.com with SMTP id ada2fe7eead31-5f1bcdf03c6so1235756137.1 for ; Mon, 26 Jan 2026 00:23:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1769415788; cv=none; d=google.com; s=arc-20240605; b=LPH6b/2WBX0aarxwX/KB4KiIxZx2zWM7z8R/9KlFehy9HQ0XsMQlRnPllftvIx+A1t qq+n7APLLSVbSgBbjsWm/N//URvpip+AbeZmLsacQRRfP1q/FCvUeqcABJA4jK1UrZ+F 0mc6dbIrRPsPVUQKWk6o2MUFt3zhRTCT7EPeVnTAaGd1RWp0JHsST3N3hr22SylAlnUJ 5c4UFs7lugEhn87vx04layVktulUVfAeI9U/zDzFjbMSoJ9nbHw7p5CcDKDBDz34KONq ja+7MFt8XcUqonsK2vlORDPbeJuIHgC0GvPGR17pfVZoAvt4PBjNa8K8VPS1npC2GaaM FKfg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=wDk5WDOGKXetPSb4Kk3w+pebJq4jYAjrp+mw8nVPuvc=; fh=Ofn+XpSLefQyxrNYeqFK5V6BgIEzMTvoqvpJ6/SQfuk=; b=iLUVqsh8GVdFb26rWShSk9kZ7tlQKP+rqdF41Fi1qVeFH/QwWwAQZ8ivTTPWjpcHCg Wq6mSNoTHe9571+NUndN8h7/U+rBFb53C0Y4CjLTfW5Pb2kqsZCBwXl8m2DFaXDP7UHz wxtKokqG5aXxaWn2g6wvK5XV5EXVXP0XSqkwMX7/BfLll1w/pcGJAvm9swuMD6XK/rk4 a9fOeHjSVRhG9bvvRlnkS22HXBTjVWiV14+psgKU9BzVjO/JYJcOpffKFPbuKiqp55Jx Vk7dsjbpeLRBqV1m/jdIU2t2LP3DUSdNrAT0l4bDp5P/E880UWg4Ko9g+2sFog+ninjr YapA==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769415788; x=1770020588; darn=lists.php.net; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=wDk5WDOGKXetPSb4Kk3w+pebJq4jYAjrp+mw8nVPuvc=; b=ITMVLgjpnFwyyAZ3xrbYZX6wcBBQpv2QkU3B5MiFp1XApjjh2L4AsgJv/N1qjQ4uYr IEatQJfivqQ5ih7O/o7pp0PgpGP8ekE31dx0cqGh9DRyKTnfa3AMOJosRBtbllyN0QGe 7IKy6urUf2jyKYOCiydH92l2HcEhkA9IT+T1HT/6XLzlf6yC0TGeO1zfvv+ZdYY/SJET ttl/lZVW9Fejhs9edaC8iqOM0a5ah9XzT9oZTHivlO9dzuzd8/erTYd6Nw9dvT6lEZUB C6JCCRg7WVBmn/HX37jBGccilFVLSgSWKGgtbK+65SRPa7L4Ar5000wI6ZFrzLOACukj Whxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769415788; x=1770020588; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wDk5WDOGKXetPSb4Kk3w+pebJq4jYAjrp+mw8nVPuvc=; b=cGaHR+gHSAP5/ClTROUWiFKWx15SmEIHp6HkJGWVg4AlpqD6K8kgh7ewX2WsDPTLHx no3ZAsPokEbh1buaY83F20UyASJuWImEg3Z6zxRI/ZxakrdSiiyn+WiMtUZzg2hqQsf+ BBeZRdWPgbAoYgJ6BXNlEtdIScV/srXsqrR0OcfInEQE7lGLDFjjHJYFby/bRUmajo/+ zyqXcM8kV9ptMAY9REwnxIAxYtRH654cLi9Yx86ejme8spG+XcAz1guRxa0rNeQ/5ig0 T3L5iWq/z64ePThNCjGdxJ213xoPFsvRhyKBr8RySV7AT6wfU78dlB106P410iPA+FVS 9o5g== X-Gm-Message-State: AOJu0YwjaNs88Y3Tvg6gQHIMr+6zcFj7dikSobGo11qHHsr58PFSAyyP 7vc7fcvCCdbi0i2CEg03y5ZqtTuoG+d6bDQDdi8iLXkyttzGca70s9Wdzhogr4IvebVzwTiZYTF sz9HQSsYREoCh6bAXSh/4IAGwKHDG9ZnSyuEFk8U= X-Gm-Gg: AZuq6aIU5c/zB175iC9xsWiuS0r0SQB58xNpDAMNWK6j7ZDxlgzqaCuRr24QsjUt0/4 uE+ewwCmD4FlemxMzIM3sxCAgneiMmVujwng5/WisOIGXVVDORwTo0g2JT/UJ/elZl3wZO3lBcu WSIMHwoN0W1ZZzV2h4NJb3ShC7VEu9UktHAcMAlhWchXLBZjxZJ+qxl9CLRmuqC4+saFuGFfBnw CCOIoXrFP/1H8hnGPQzvzCEX4WiPvnjj7G8J6wsnM/DzU8tph+XWH202IjVXQT7d1ECbHelcawa lrFOho7He6/az1GFoYr35lP4UsM= X-Received: by 2002:a05:6102:38d3:b0:5f1:606f:2a1e with SMTP id ada2fe7eead31-5f57660a4fdmr918933137.43.1769415787517; Mon, 26 Jan 2026 00:23:07 -0800 (PST) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <4a42e150-44af-4240-9854-2d47d067d760@app.fastmail.com> In-Reply-To: <4a42e150-44af-4240-9854-2d47d067d760@app.fastmail.com> Date: Mon, 26 Jan 2026 10:22:55 +0200 X-Gm-Features: AZwV_Qg6Um1Et09ErwyLZPSOjue5J9J76a2JXx3Xe4OsmpnEyqX6kCweexi1Z28 Message-ID: Subject: Re: [PHP-DEV] [RFC] True Async RFC 1.7 To: Larry Garfield Cc: php internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: edmond.ht@gmail.com (Edmond Dantes) > Most RFCs have an example in the introduction of what the proposed synta= x looks like in a small but meaningful example. Please include such, as it= helps "set the stage" and provide context for the rest of the RFC. usage examples are provided immediately after the API Overview, as agreed. > As I've said before, I'd rather have keywords than functions for the main= API. As discussed earlier, introducing new keywords is better addressed in a separate RFC. > getAwaitingInfo(): array - Hell no, no struct arrays. Make it a class. The getAwaitingInfo function is intended to retrieve debugging information that can be used for telemetry or debugging purposes. Different reasons for suspending a coroutine may have different metadata, which is difficult to standardize. Therefore, an associative array with keys is used as the ideal data structure for storing information without a contract, and one that is easy to serialize. > Function name strings should basically never be used again. (Another arg= ument in favor of keywords.) The question goes beyond the scope of this RFC. However, what would be useful to discuss is the possibility of narrowing the interface down to Closure. For some reason, a year has already passed, and that discussion still has not happened. > "The non-blocking version of the file_get_contents function is not part = of this RFC." - Wait, I'm confused. This is a consequence of the lack of agreement on what should be included in an RFC and what should not. I will remove this block. > The examples seem very inconsistent. Some are using foo(...), The term =E2=80=9Cinconsistency=E2=80=9D cannot be applied in this case, si= nce all examples are consistent with subsets that belong to the same set. In PHP, all these expressions are callable. > - In Fibers, in the basic example, "start() blocks until the fiber comple= tes" - I assume that means it blocks the calling coroutine? Or does it blo= ck the whole system until it completes? Non-blocking behavior is the default. Therefore, of course, it is the coroutine that is blocked. > - I have no idea what it means for coroutines to be "symmetric". This is= stated as a thing, but I have no clue what that means. That makes much of= the Fibers section incomprehensible. There is a terminology error here. It should be =E2=80=9Casymmetric.=E2=80= =9D: >> Asymmetric coroutine mechanisms (more commonly denoted as semi-symmetric= or semi coroutines) provide two control-transfer operations: one for invok= ing a coroutine and one for suspending it, the latter returning control to = the coroutine invoker. >> While symmetric coroutines operate at the same hi= erarchical level, an asymmetric coroutine can be regarded as subordinate to= its caller, the relationship between them being somewhat similar to that b= etween a called and a calling routine. In other words, according to the official PHP documentation, the following conditions must be met: >> Suspends execution of the current fiber. The value provided to this meth= od will be returned from the call to Fiber::start(), Fiber::resume(), or Fi= ber::throw() that switched execution into the current fiber. > - I will have to defer to the existing async gurus This is not complex enough to require asking a guru. Fibers transfer control according to the following scheme: ``` Fiber::start() -> Fiber::suspend() -> Fiber::resume() FiberA FiberB FiberA ``` A -> B -> A This logic remains valid for coroutines as well: ``` Fiber::start() -> Fiber::suspend() -> Fiber::resume() CoroA CoroB CoroA ``` A -> B -> A I hope someone actually read the Fibers RFC, right? > If I'm reading that correctly, it means `span(very_long_function(...))` w= ill start a coroutine, but not assign it to a variable. > So I cannot track it or refer to it, but it will still run in the backgro= und until it completes, at which point it will get GCed. Is that correct? Yes. The spawn function will return a Coroutine object, which can be used like any other object. The reference count of such an object will be 2. If the result of spawn is not used, the coroutine will live for as long as it is executing. > The FrankenPHP example linked to... doesn't seem to do anything to start = a coroutine. I don't know what it's supposed to be demonstrating other tha= n FrankenPHP itself. Here, FrankenPHP handles HTTP requests in separate coroutines. That is, it demonstrates how coroutines can help improve performance for a web server. The coroutine is created inside the FrankenPHP extension, and the user provides the request-handling function. Thus, each request is handled in a separate coroutine. > What is the difference then between $coroutine->finally() and register_sh= utdown_function(), when the current coroutine happens to be main? There is no difference. Most likely, the finally handler will be invoked before register_shutdown_function, although I am not 100% sure. > Non-Async code can use Cancellation, but... what does that even mean or d= o? Why would someone use it? > This is sneaking in a 3rd error type without much guidance. catch(Throwa= ble) is surprisingly common (rightly or wrongly), so this feels like a majo= r pothole potential. In this RFC, there is no non-async code. Where does this text come from? > Oh crap, Scopes are now a SEPARATE RFC, of similar length? I thought that when you voted the previous version of the RFC, you had at least read the first page. I see. In fact, the Scope API was separated a long time ago. This was done in order to reduce cognitive load. > This seems mostly logical as a low-level API The term *low-level* is used incorrectly here. *Low-level* is applicable when an API exposes internal implementation details or operates at a lower level of abstraction. For example, drawing a pixel versus drawing a point. Drawing a pixel is low-level. In this case, coroutines themselves (unlike Fibers in the past) are a high-level abstraction that hides all implementation details from the user. If you analyze the API surface of Scope versus this RFC, you will see that the APIs are at the same level of abstraction. Therefore, neither the Scope API nor the Async Base API is low-level. > I want a *safe* API. I am not convinced those are compatible. And I ce= rtainly do not want to see the low-level API in one release and then have t= o wait for the next release for the safer API. In programming, the term =E2=80=9Csafe=E2=80=9D is used in different meanin= gs and is usually not applied in the context in which you are using it. I do not recommend using the term **safe** in this case, as the U.S. security services might read this message and ban the use of PHP on the grounds that PHP has no *safe* variables. In this case, the code remains safe even without the Scope API. > Having pipes and PFA in separate releases is bad enough. :-) It was originally assumed that the Scope API, as well as the Context API, would be approved immediately after this RFC. However, given the pace of the discussion, or rather the complete lack of it, this seems unlikely. > That this allows for zombie coroutines or "lost" background coroutines to= exist is, to me, a major problem. You wrote that something is a problem, but you forgot to explain why it is a problem. The Scope API does not prohibit the use of zombie coroutines. > As I've said before, I don't like await, spawn, etc. being free-standing = functions rather than keywords. That is very limiting on the syntax they c= an use. It also means, as the examples show, we get this pattern very ofte= n: Nevertheless, this is the only reasonable solution for the gradual approval of the API. Moreover, even if keywords are added later, the functions will not need to be removed. > $result =3D $fn |> spawn(...) |> await(...); (wipes away bloody tears) Oh God, why am I reading this :) A pipe is sequential execution of something. That means if something asynchronous is called inside a pipe, the pipe must wait for it out of the box, without any additional functions. In other words, a =E2=80=9Cdereferencing=E2=80=9D operation of the future m= ust be applied: ```php $result =3D $data |> strtolower(?) |> spawn(someFunction(...), ?) |> strtoupper(?); ``` I haven=E2=80=99t studied the new syntax yet, but I think the idea is clear= . In other words, the pipe must wait for the completion of the asynchronous operation. If PHP can adopt a new, cleaner syntax for closures, then it will be possible to introduce a new spawn keyword for coroutines and create a single, elegant syntax. But in essence, this changes nothing. ---- Ed.