Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129434 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 9A4B61A00BC for ; Mon, 24 Nov 2025 15:04:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1763996681; bh=9JJT8FoDBaOoEuRYxw/LtEqAzdNQXaa0P1edRICj028=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=PyTx+Vklew2yPMvHoQ7kjBfkFNh1jK975MIesUchMhnxDQuncYkeYiDxX/TkCxlfw oH2voGBZoz9I6E92TSOlyHlshhCAS70kwdvI0O8doh9hFGyqqwtFDP0/53eo3+RZm3 YajS1UL0IIWbYvuOWpXAwMmizG469QAp/x69bti6Y76qRLhzJoHNXXDEQOYPpx9ILr GDfmUxrQ5fzzRBmhdPwCc5j2N+vw10nekYyzrDo3zik8bSzEzCtKgyZzDmo0TCADSN mfjCp71EQgP28Wn3L+M74O/lr4WX4gezU2bog8dRh+I6WPzRbbFkW7zUrl67uf/MAO YyIED5JKAVaOQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 8CB1B180339 for ; Mon, 24 Nov 2025 15:04:39 +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=1.8 required=5.0 tests=BAYES_50,DMARC_NONE, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, HTML_MESSAGE,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-oi1-f175.google.com (mail-oi1-f175.google.com [209.85.167.175]) (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, 24 Nov 2025 15:04:39 +0000 (UTC) Received: by mail-oi1-f175.google.com with SMTP id 5614622812f47-450bbac0368so2451227b6e.1 for ; Mon, 24 Nov 2025 07:04:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763996674; x=1764601474; h=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=9JJT8FoDBaOoEuRYxw/LtEqAzdNQXaa0P1edRICj028=; b=VfTWIV3r0gsj3kGB+KowgiXWhr8xX/gYajPvrkz4FUtgogICanU3iYMAUStBdQz0zJ E//WaCYFQVikq5qw88F87l1Dzmg17RFeSZEpFEZdWNqub8nMuGMLOfHdGaP8LRTkNwtH HhVMvTwnOpuXyMokO86aarlateDkRteqRUwcgodmyad6qWTSoG9hUybWqzkKqo60SVJI k2jaIpnLipZXX44eqmaf2VOPE7Wc1s7y96y//5amDPuhJI9ldQCnitGN9LipsjbRVDyB toAKj1vK+RDp8hY8R9B2RxHG4x4uOz2OxeRoq6fcNpZb3LMWvK00PIS2KBmxC6QskJ02 fWWw== X-Forwarded-Encrypted: i=1; AJvYcCUkLLntjsYowrcruFJtEhe70fCC74uiXNq7b3YV558vsT9bhgeTJfqAxe8uQ6BZpceaNHbPhdKimbs=@lists.php.net X-Gm-Message-State: AOJu0Yzj95v5nkQu0L7TE/SmOQ/SznUqM0R6resHnQ6cRQ0yiOzRB3z8 A6KTG3JpayGdGRpSC4Mcggt00RO38J174uzK+f5Q2zL3z3u/fhm70cs3LIKQkHpv4bTqS0pEzlw W5IjAtknqplt/1MIgPu4qKBzB5XopKUc= X-Gm-Gg: ASbGncuOAOE/IUD/rQcvw1a4vZuXSEcsawxl4R0qHJe33YRQAM43j6NzfAxt/vSlq45 je2RVCBbwkLebzc3Eof3j7HxxXUaIdkQIQ8cVjKcP2yRaaXW5C1/NzZWo1850oxm4/MXaaemfxb WV1jKyG7hsE0jP+UYt0RwilmwqsoN/es2bzp8kDtKwP19OPLCNA3Z4jb4kvlVKUnDm0k7Is4fB7 LuuHbaIwoHKJ0JZcn4v8zBPeDSV3CM+5TMvy/b0sbsq0sHrzye+9vYvXUYx478D5nndVQ== X-Google-Smtp-Source: AGHT+IF4D/I64sxIEF9IXIbR6pJdwldxYxVCkEujZq2sRffXVNvS5d3YVg/JXwK32Y9FDhAepuWNU4is0lFFgKfT7c4= X-Received: by 2002:a05:6808:3c46:b0:450:cfe8:28aa with SMTP id 5614622812f47-45112b65f08mr4719631b6e.28.1763996673128; Mon, 24 Nov 2025 07:04:33 -0800 (PST) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <1402906904.784903.1763811759896@email.ionos.de> <2015208655.784984.1763811978476@email.ionos.de> <980296152.1071.1763813573083@email.ionos.de> <92865666.4510.1763818506332@email.ionos.de> <329450798.8037.1763822426377@email.ionos.de> <9287c46c-bc63-4dd0-9792-0f9421959589@rwec.co.uk> In-Reply-To: Date: Mon, 24 Nov 2025 16:04:19 +0100 X-Gm-Features: AWmQ_bkmVCXG1ZzkmgdTy2ti3GF-QrbXIw87nqL9KH2bjjC4E1gGFwKevLlR_gs Message-ID: Subject: Re: [PHP-DEV] [VOTE] True Async RFC 1.6 To: Edmond Dantes Cc: "Rowan Tommins [IMSoP]" , internals@lists.php.net Content-Type: multipart/alternative; boundary="000000000000163b820644587b95" From: bukka@php.net (Jakub Zelenka) --000000000000163b820644587b95 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, On Mon, Nov 24, 2025 at 2:23=E2=80=AFPM Edmond Dantes = wrote: > A programmer working with coroutines will not be able to use static or > global variables to pass state. > > They have only two ways to do it: > 1. Function parameters > 2. use to capture variables in a closure > > This makes it impossible to accidentally shoot yourself in the foot. A > developer can still do something silly by explicitly passing objects > between coroutines, but now they are doing it consciously. > > Although even here we can go further and create something similar to > ownership transfer of an object. In other words, an explicit semantics > that clearly specifies what to do with the object: > > 1. Should the object be **moved** between coroutines? > This could be quite problematic for internal objects that might depend on global that will switch. > 2. Should the object be **cloned**? > Something like this should be done explicitly through channels otherwise it would be quite strange semantically for users. > 3. Is the object a special **shared** object that can be safely passed > around? > > I think it should be the only allowed case. > Such semantics makes coroutines thread-safe. > > In other words, by designing a special parameter-passing semantics for > coroutines, we can create a perfect specification for coroutines that > can be run both in another thread and in the current one. > At the same time, the memory model becomes equivalent to Erlang=E2=80=99s > model, where there are no shared objects except for specific special > ones. > > Such a change requires adding special **Shared** objects to the > language, which can be safely used across different threads. And > developers will no longer be able to use reference-based variables, > except within something like `SharedBox`. > At the same time, implementing multi-threading support is not required > immediately. But once this capability is added, the language semantics > will already be fully prepared for it. > > So props/cons: > > 1. Coroutines become safe execution containers that cannot > accidentally damage shared memory. > 2. Old code requires no changes. > 3. New coroutines cannot harm old code. And if parameter-passing > semantics are introduced, they won=E2=80=99t be able to harm it at all. P= HP > will forbid a programmer from even trying to pass memory to another > coroutine just like that. > 4. The language semantics make it possible to describe fully > thread-safe code, which can be added in the future at any time without > major changes. > > **The cost:** > 1. a developer must write a bit more code to work with shared objects > between coroutines. > 2. In such a memory model, you cannot obtain the result of a > coroutine=E2=80=99s execution twice. > 3. And this changes the philosophy of awaiting a coroutine: only one > coroutine can wait for another. However, this limitation has many > positive sides, because it greatly simplifies debugging. > > Such a memory model is quite modern and yet not new. It is essentially > supported by Go, Erlang, and other next-generation languages. > Therefore, if PHP=E2=80=99s strategy is to eventually become a language w= ith > parallelism while guaranteeing coroutine safety with respect to shared > memory, then this is the right path. > But I want to warn once again about the price that must be paid from > the developer=E2=80=99s point of view. A developer will no longer be able= to > use reference variables or pass objects between coroutines. > > If we could make this work, then it could be a much better result as it could open doors for true parallelisation. It will add more limitations in terms of sharing code but I think it would be worth it. I think the first thing for that would be good to look at is to make the needed changes for TSRM which would be already useful for FrankenPHP : https://github.com/php/frankenphp/discussions/1980 . The context switches will likely become more expensive but should be still cheaper than long IO. But obviously not idea if IO is available and switch is not needed. The scheduler might need to be a bit smarter and try to reduce switches though. I started writing IO ring library that is a thin wrapper for liburing on Linux and it has compatibility layer for other platforms using IO threads: https://github.com/libior/ior . This is still limited and supports only basic ops but I plan to add more ops (including epoll based ops). Also it will need Windows support.. But the advantage of ring buffer is that it can significantly reduce syscalls and check multiple completions in one go (it has already queue for them) so it could more easily reduce number of switches (e.g. it can immediately get info whether IO is available by going through all the completion events). I think it should be a bit more flexible for scheduler. Anyway it's more a detail at this stage but maybe something to think about later. Kind regards, Jakub --000000000000163b820644587b95 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

On Mon, Nov 24, 2025 at 2:23= =E2=80=AFPM Edmond Dantes <edmond= .ht@gmail.com> wrote:
A programmer working with coroutines will not be able to use static or
global variables to pass state.

They have only two ways to do it:
1. Function parameters
2. use to capture variables in a closure

This makes it impossible to accidentally shoot yourself in the foot. A
developer can still do something silly by explicitly passing objects
between coroutines, but now they are doing it consciously.

Although even here we can go further and create something similar to
ownership transfer of an object. In other words, an explicit semantics
that clearly specifies what to do with the object:

1. Should the object be **moved** between coroutines?
=
This could be quite problematic for internal objects that mi= ght depend on global that will switch.
=C2=A0
2. Should the object be **cloned**?

Som= ething like this should be done explicitly through channels otherwise it wo= uld be quite strange semantically for users.
=C2=A0
3. Is the object a special **shared** object that can be safely passed arou= nd?


I think it should be the only allowed = case.
=C2=A0
Such semantics makes coroutines thread-safe.

In other words, by designing a special parameter-passing semantics for
coroutines, we can create a perfect specification for coroutines that
can be run both in another thread and in the current one.
At the same time, the memory model becomes equivalent to Erlang=E2=80=99s model, where there are no shared objects except for specific special
ones.

Such a change requires adding special **Shared** objects to the
language, which can be safely used across different threads. And
developers will no longer be able to use reference-based variables,
except within something like `SharedBox<T>`.
At the same time, implementing multi-threading support is not required
immediately. But once this capability is added, the language semantics
will already be fully prepared for it.

So props/cons:

1. Coroutines become safe execution containers that cannot
accidentally damage shared memory.
2. Old code requires no changes.
3. New coroutines cannot harm old code. And if parameter-passing
semantics are introduced, they won=E2=80=99t be able to harm it at all. PHP=
will forbid a programmer from even trying to pass memory to another
coroutine just like that.
4. The language semantics make it possible to describe fully
thread-safe code, which can be added in the future at any time without
major changes.

**The cost:**
1. a developer must write a bit more code to work with shared objects
between coroutines.
2. In such a memory model, you cannot obtain the result of a
coroutine=E2=80=99s execution twice.
3. And this changes the philosophy of awaiting a coroutine: only one
coroutine can wait for another. However, this limitation has many
positive sides, because it greatly simplifies debugging.

Such a memory model is quite modern and yet not new. It is essentially
supported by Go, Erlang, and other next-generation languages.
Therefore, if PHP=E2=80=99s strategy is to eventually become a language wit= h
parallelism while guaranteeing coroutine safety with respect to shared
memory, then this is the right path.
But I want to warn once again about the price that must be paid from
the developer=E2=80=99s point of view. A developer will no longer be able t= o
use reference variables or pass objects between coroutines.


If we could make this work, then it could be a muc= h better result as it could open doors for true parallelisation. It will ad= d more limitations in terms of sharing code but I think it would be worth i= t.

I think the first thing for that would be good = to look at is to make the needed changes for TSRM which would be already us= eful for FrankenPHP :=C2=A0https://github.com/php/frankenphp/discussions/1980 .

The context switches will likely become more expensiv= e but should be still cheaper than long IO. But obviously not idea if IO is= available and switch is not needed. The scheduler might need to be a bit s= marter and try to reduce switches though. I started writing IO ring library= that is a thin wrapper for liburing on Linux and it has compatibility laye= r for other platforms using IO threads:=C2=A0https://github.com/libior/ior . This is still limited and s= upports only basic ops but I plan to add more ops (including epoll based op= s). Also it will need Windows support.. But the advantage of ring buffer is= that it can significantly reduce syscalls and check multiple completions i= n one go (it has already queue for them) so it could more easily reduce num= ber of switches (e.g. it can immediately get info whether IO is available b= y going through all the completion events). I think it should be a bit more= flexible for scheduler. Anyway it's more a detail at this stage but ma= ybe something to think about later.

Kind regards,<= /div>

Jakub
--000000000000163b820644587b95--