Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130293 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 47B5D1A00BC for ; Wed, 11 Mar 2026 21:07:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1773263278; bh=k34q1N/6UAl1Jqom19PQOXndvndiA8G/eMn4CFI58Js=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=QjxLWockBZ7BdhK4oRlV2ovQckgxLddEscjDheSZ6MM1k9woHpzk562RuX/c/zgs8 VRkUA4+SovWd+UnlAqQ/Lwy/5jyARPoosi0SmFfaEJ7XD/OCnJMb0gbqbSTkAurZzu eZMBxT/aDcq4bcE5ihUqpW0meu6d+pPt2SHRFixWCluceajb7ZJII0zxsWfMsOyt7m h3flJhMZX/erQ9qjf8K2GBnmOyTu+9UtwiqMCn/f7KykCGpYtpIbAhWtivxVSFWLwT +skVJ7A1J1QywWyHYFn5sWQUTm838b+TCwzy2HyZ0xExh+YJgP2/B0ocoLvwk29hyh wJByJGCbFPx0Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C9F97180084 for ; Wed, 11 Mar 2026 21:07:57 +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.7 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DMARC_NONE,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-oa1-f54.google.com (mail-oa1-f54.google.com [209.85.160.54]) (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, 11 Mar 2026 21:07:57 +0000 (UTC) Received: by mail-oa1-f54.google.com with SMTP id 586e51a60fabf-40f387a688dso299440fac.0 for ; Wed, 11 Mar 2026 14:07:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1773263271; cv=none; d=google.com; s=arc-20240605; b=bYeQs6AmcNMVWhsDhr/zrFLuty85WDFPrDn1d0T/A5gktPf3Bk2rP+M02hVxm20vpW /LgINUjGSOnR/YJ4h6wdz+coIK4SuYF5ZIEYdhHZrBaOhIIzqC5s6ot1QBDmyqXJqznM AEeM24tUNmlZf7C4zuIol3LfZT/M0xVxJjCs17Sadn+dZ1E7Sm+F3Ylcc5PMyQ2Yq5XX pQbJmFIyjJ78U0IQO/3/Lr4DPIgqx1d50MLuTSx7QrFAmmGTBzDbQanbEg9vUOi+0E3H 104VGBuLk7gKIE7JDfMJsQyc+miS+qtsfJLTenQsqG4j38OW34aJOVDIPom9uAWA0/qF /p3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version; bh=k34q1N/6UAl1Jqom19PQOXndvndiA8G/eMn4CFI58Js=; fh=xX59M9k2LJe5CkjPpBTRX27Ve3+5hYeaIKPXnbjUkb8=; b=djmBxulAxmByxTU8qXYMo73srJOxJLua26CeyEDG2/H+CxtK1vUC3vqQBLUWiGHMkX nVhkWxC51jqSlsQRxwZLtnpS7ZGvk8JwRtE+b0rVjdLCpE7oV08czQZeANf2GFXa3lRc 2i+pz0Ry5rBIbTqYhT9R58p9Jl7CWE7FwmXcGYsmr77RQTPsUGW1ton5nFMisvDGH2Hs TGeLhVcT1f8U0130gGvao++5sEc4rbOzlDsPxHORUd31QXODKNL1VmqK9LF/I5h9f4Zw v8y0CugSBhw2O1M94oBwIvDfH5nBlcP0VRn9sPMNE8VdQYc1Du3uD2Sc8QSnKUwv7UAK 1NAA==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773263271; x=1773868071; 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=k34q1N/6UAl1Jqom19PQOXndvndiA8G/eMn4CFI58Js=; b=rciBLuvfvswfbDw6MITlMkPTyFrc+88p3rro7p/bU1Tm/dhAvEC7yzvMz8DKeFqQ8B QMhX29bj13dZYJE/h3ij5ovEzWtBzlptobGb+SlAp27cb9DBk0axtmHzuY7seqXSvgwH bh8Wkk5jKI4X5gGwdJA21kYBEhu40cyyW2I/sxTEYfXD4cGsUyLsfLZg79t03wlG+pwD HeAGmkzGKtlYGPVYwxPDbA0VJl+XV5kwGwEEBqj/fXFNfTal/vEXDqw9jtXwmLxqReMT dDq801Lm2Vr4p6rPegnW/IYM82Z1MAmjhJzrc4xPXm1s0Yhi2Cx74IUaBnfvLK+5mbi7 oLyQ== X-Gm-Message-State: AOJu0YzKOStOS9Fatz0M4uA21J8nU58xedHAsThwifaiy3d9jVfWKJXS CmCyAbjU4HGDgmaTdb9mUQmsSebgNhp3+z9Bw/0BMCtQLr39IQxB5Gj2Ye+JgLXmOrRwAm1QIuy 8wBgeBdRWUJhLo0URC8W+/FmWXBxDuhvRXg1z X-Gm-Gg: ATEYQzwqNrMnP07vLkjitzM4GYihfV6LE1LUztgnMlXtuzxiyv5PNTyF1m3R4BQRWxu j9KsDnNyjm3sFPYzp6h/7n7Vq5Wq5y3AXWcXaB0pCqvPNjIFwuPVndI8AsFPBwuAhHjn8aC7zbM fiLIm5JHpuP33EdxmGYmBk3vg829BTlX1dAkAzXVjDbTQDg93eZcIQIq2iu+7BrucZN0la7eY97 qpw7KbM1djvDqR9ko+k59xAMPlKZm5tVetSzKVQgNqpapnTL6FNUVY5bG6rd+eVl9KBEt/E9FJg Awb8NY0= X-Received: by 2002:a05:6870:b289:b0:417:3441:6c54 with SMTP id 586e51a60fabf-4177c8be4eamr2479346fac.27.1773263271439; Wed, 11 Mar 2026 14:07:51 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <926a26a6-eb89-49aa-a387-6cc79caa29c1@bastelstu.be> In-Reply-To: Date: Wed, 11 Mar 2026 22:07:40 +0100 X-Gm-Features: AaiRm50LRCXUvrSv9_2BwoZ4g1kJNQFZeQQ2FHmn8AiicUPLqinYVTYV6dZNYHM Message-ID: Subject: Re: [PHP-DEV] [RFC] Polling API To: =?UTF-8?Q?Tim_D=C3=BCsterhus?= Cc: PHP internals list Content-Type: multipart/alternative; boundary="000000000000633233064cc60717" From: bukka@php.net (Jakub Zelenka) --000000000000633233064cc60717 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, On Sun, Mar 8, 2026 at 12:27=E2=80=AFPM Tim D=C3=BCsterhus wrote: > Hi > > Am 2026-02-22 17:16, schrieb Jakub Zelenka: > > Thanks for the feedback! > > Thank you. I've given the RFC another read now and have some minor > things to remark: > > 1. I don't think it makes sense for the majority of the classes to be > serialized, because they rely on =E2=80=9Cin-process=E2=80=9D state, spec= ifically file > descriptors. This includes Context, Watcher, and the handles. > Serializing the enum and Exceptions by themselves is fine. The RFC > should note that serialization is prevented and the implementation > adjusted. > > Sure this was my omission - I marked all classes as not serializable. > 2. Similarly for any new classes, I recommend to always set > `@strict-properties` to prevent shenanigans with folks accidentally > adding dynamic properties to these classes. This should be done for > everything, including the exceptions. > > And I also marked them with @strict-properties > 3. I have a question as someone who never used Fibers in production: Is > it necessary or helpful for the API to provide some =E2=80=9Cconvenience= =E2=80=9D > functionality related to Fibers (e.g. automatically suspending or > unsuspending Fibers)? I'm asking now, because adding that functionality > later might be a breaking change in behavior. If it's not necessary or > can be added in a backwards compatible way, that's fine, of course. > > I can't really think about something reasonable here - it seems better not to mix it. And even if we wanted to add something, I think it could be backward compatible. > > On Sun, Jan 18, 2026 at 1:24=E2=80=AFPM Tim D=C3=BCsterhus wrote: > >> - Context::wait() takes a millisecond timeout. This feels > >> insufficiently > >> granular. I am wondering if we should rather use either micro (as > >> returned by microtime) or nanoseconds (as returned by hrtime) - or > >> possible an instance of DateInterval (which would use microsecond > >> resolution). > >> > > > > Yeah this makes sense. I used the same convention that is used in > > streams > > which means two params so it is changed to: > > > > public function wait(int $timeoutSeconds =3D -1, int $timeoutMicrosecon= ds > > =3D > > 0, int $maxEvents =3D -1): array {} > > I feel that using two parameters is providing for a very clunky API, > which is also acknowledged by the doc comment on $timeoutMicroseconds > "Only used when $timeoutSeconds >=3D 0". I would have suggested > DateInterval again, but I'm just seeing that it seems there is no > documented way to manually construct a DateInterval with microseconds. > > Perhaps the following suggestion would be a good middleground: > > - Change $timeoutSeconds to int|null: If null is specified, the timeout > is infinite. > - Throw ValueError if $timeoutSeconds < 0 > - Throw ValueError if $timeoutMicroseconds < 0 > - Throw ValueError if $timeoutSeconds =3D=3D=3D null && timeoutMicrosecon= ds > > 0 > > `null` is a much more natural value for =E2=80=9Cno timeout=E2=80=9D and = by throwing > ValueError we make sure that we don't have a situation where a parameter > is silently ignored. > Yeah this makes much more sense and stream_select works similar - not sure why I didn't add it. It's fixed. > > Similarly for `$maxEvents` it might make sense to use `null` for =E2=80= =9Cuse a > default value=E2=80=9D? Also: What happens if I specify `$maxEvents =3D 0= `? Is > this useful? > 0 was used to select default so the same as -1. I changed it to null and it now has to be positive value. > > > > >> - For Handle I am wondering about abstract class vs interface. Since > >> the > >> Handle presumably doesn't have any non-abstract methods, an interface > >> feels more correct / more flexible. > >> > > > > I have been considering this already and there are reasons why I prefer > > abstract method here. > > > > The abstract method is better for internal implementation and limit > > overhead of PHP calls that would be required for interface. The > > advantage > > is that I can use internal struct API through C operations which allows > > bypasing the call and can do optimization for some backends - e.g. > > timeouts > > for kqueue don't need file descriptor. > > You can bypass the =E2=80=9CVM method=E2=80=9D for interfaces and abstrac= t methods > alike. A good example would be ext/random which allows changing the > engines by the Random\Engine interface, but for engines implemented in > C, the Randomizer doesn't go through the userland API, but instead calls > the engines directly. > > Yeah I think perf would be solvable here actually. > > I also think that there is not really much use case for user space to > > implement their own handles so such interface would be used only > > internally > > anyway. > > This applies equally to interfaces and abstract methods. The abstract > base class however will make it much weirder when a specific (future) > handle might need to implement additional interfaces or abstract > classes. > > > In addition interface would effectively expose the internal stream fd > > which > > is currently hidden and makes harder messing up with stream fd which > > might > > cause various issues. > > I don't understand that point. For both an interface and an abstract > method, the method would exist on the child class and thus can be called > by a developer. > > Well if it is abstract, then the method can be protected and because the classes are final, user spaces cannot call it. But for interface I would need to make it public which means that StreamHandle would need to expose callabable (public) method. I know that I could just return 0 and use different handling internally but I think this would be surprising and created obvious inconsistency. I mean it's fine if the calls happen internally but if the exposed methods are just dummy and return nonsense for user space, then I don't think it would be a good design. Kind regards, Jakub --000000000000633233064cc60717 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

On Sun, Mar 8, 2026 at 12:27= =E2=80=AFPM Tim D=C3=BCsterhus <tim@= bastelstu.be> wrote:
Hi

Am 2026-02-22 17:16, schrieb Jakub Zelenka:
> Thanks for the feedback!

Thank you. I've given the RFC another read now and have some minor
things to remark:

1. I don't think it makes sense for the majority of the classes to be <= br> serialized, because they rely on =E2=80=9Cin-process=E2=80=9D state, specif= ically file
descriptors. This includes Context, Watcher, and the handles.
Serializing the enum and Exceptions by themselves is fine. The RFC
should note that serialization is prevented and the implementation
adjusted.


Sure this was my omission - I marked a= ll classes as not serializable.
=C2=A0
2. Similarly for any new classes, I recommend to always set
`@strict-properties` to prevent shenanigans with folks accidentally
adding dynamic properties to these classes. This should be done for
everything, including the exceptions.


And I also marked them with=C2=A0@stri= ct-properties
=C2=A0
3. I have a question as someone who never used Fibers in production: Is it necessary or helpful for the API to provide some =E2=80=9Cconvenience=E2= =80=9D
functionality related to Fibers (e.g. automatically suspending or
unsuspending Fibers)? I'm asking now, because adding that functionality=
later might be a breaking change in behavior. If it's not necessary or =
can be added in a backwards compatible way, that's fine, of course.


I can't really think about somethi= ng reasonable here - it seems better not to mix it. And even if we wanted t= o add something, I think it could be backward compatible.
=C2=A0<= /div>
> On Sun, Jan 18, 2026 at 1:24=E2=80=AFPM Tim D=C3=BCsterhus <tim@bastelstu.be> wro= te:
>> - Context::wait() takes a millisecond timeout. This feels
>> insufficiently
>> granular. I am wondering if we should rather use either micro (as<= br> >> returned by microtime) or nanoseconds (as returned by hrtime) - or=
>> possible an instance of DateInterval (which would use microsecond<= br> >> resolution).
>>
>
> Yeah this makes sense. I used the same convention that is used in
> streams
> which means two params so it is changed to:
>
> public function wait(int $timeoutSeconds =3D -1, int $timeoutMicroseco= nds
> =3D
> 0, int $maxEvents =3D -1): array {}

I feel that using two parameters is providing for a very clunky API,
which is also acknowledged by the doc comment on $timeoutMicroseconds
"Only used when $timeoutSeconds >=3D 0". I would have suggeste= d
DateInterval again, but I'm just seeing that it seems there is no
documented way to manually construct a DateInterval with microseconds.

Perhaps the following suggestion would be a good middleground:

- Change $timeoutSeconds to int|null: If null is specified, the timeout is infinite.
- Throw ValueError if $timeoutSeconds < 0
- Throw ValueError if $timeoutMicroseconds < 0
- Throw ValueError if $timeoutSeconds =3D=3D=3D null && timeoutMicr= oseconds >
0

`null` is a much more natural value for =E2=80=9Cno timeout=E2=80=9D and by= throwing
ValueError we make sure that we don't have a situation where a paramete= r
is silently ignored.

Yeah this makes mu= ch more sense and stream_select works similar - not sure why I didn't a= dd it. It's fixed.
=C2=A0

Similarly for `$maxEvents` it might make sense to use `null` for =E2=80=9Cu= se a
default value=E2=80=9D? Also: What happens if I specify `$maxEvents =3D 0`?= Is
this useful?

0 was used to select defau= lt so the same as -1. I changed it to null and it now has to be positive va= lue.
=C2=A0
> I also think that there is not really much use case for user space to<= br> > implement their own handles so such interface would be used only
> internally
> anyway.

This applies equally to interfaces and abstract methods. The abstract
base class however will make it much weirder when a specific (future)
handle might need to implement additional interfaces or abstract
classes.

> In addition interface would effectively expose the internal stream fd =
> which
> is currently hidden and makes harder messing up with stream fd which <= br> > might
> cause various issues.

I don't understand that point. For both an interface and an abstract method, the method would exist on the child class and thus can be called by a developer.


Well if it is abstract, then the metho= d can be protected and because the classes are final, user spaces cannot ca= ll it. But for interface I would need to make it public which means that St= reamHandle would need to expose callabable (public) method. I know that I c= ould just return 0 and use different handling internally but I think this w= ould be surprising and created obvious inconsistency. I mean it's fine = if the calls happen internally but if the exposed methods are just dummy an= d return nonsense for user space, then I don't think it would be a good= design.=C2=A0

Kind regards,

<= div>Jakub=C2=A0
--000000000000633233064cc60717--