Hello,
I would like to introduce a new polling API RFC that is part of my stream
evolution work:
https://wiki.php.net/rfc/poll_api
Kind regards,
Jakub
Hi
Am 2025-10-30 22:06, schrieb Jakub Zelenka:
I would like to introduce a new polling API RFC that is part of my
stream
evolution work:
Thank you for the RFC. I've taken a first skim of the proposal and it
immediately raised the question of naming and namespacing in particular.
Our naming policy at
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#bundled-extensions
says that “namespaces SHOULD be used” and given that this is a
completely new API, I think we should namespace them.
My understanding is that the proposed API relies on a file descriptor
and not something like a timeout. It therefore makes sense to me to put
it into a namespace Io\Poll; or similar. We would then also have:
namespace Io;
class IoException extends \Exception {}
namespace Io\Poll;
class PollException extends \Io\IoException {}
The StreamPollHandle method should possibly be placed in the global
namespace still, since the stream functions are sitting there - and a
SocketPollHandle would of course be sitting in the namespace of the
Sockets extension.
- As for the PollBackend enum.
Is there a reason why this is a backed enum? Generally speaking enums
should not be backed, unless there is a good reason for this. I don't
think there is in this case - and none of the native enums are backed so
far.
- Exception-wise.
StreamPollHandle::__construct(): This should probably be a ValueError,
not a PollException, since passing an invalid stream is a programmer
error.
In the other cases it probably makes sense to further split the
PollException into purpose-built exceptions according to the Throwable
policy at
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables
(“The exception message MUST NOT be the only means of distinguishing
exception causes that the user might want to handle differently.”).
As an example PollContext::__construct() should probably throw a
BackendUnavailableException or something like this. For
PollContext::add() I'm wondering in which cases a handle “cannot be
added”. Is this an error situation that users will encounter in the real
world? Similarly, when can PollContext::wait() fail?
- PollBackend
Is the availability of the backends known at compile time of PHP or at
runtime only? Depending on that it might make sense to only
conditionally define the enum cases, allowing users to check
availability with defined() or checking the output of ::cases().
Alternatively, a public static function getAvailableBackends(): array
could be added.
I'll give the proposal a more in-depth read at a later point, but this
email should already provide for some discussion points.
Best regards
Tim Düsterhus
Hi,
Hi
Am 2025-10-30 22:06, schrieb Jakub Zelenka:
I would like to introduce a new polling API RFC that is part of my
stream
evolution work:
Thank you for the RFC. I've taken a first skim of the proposal and it
immediately raised the question of naming and namespacing in particular.
Our naming policy at
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#bundled-ewill
be alwaysxtensions
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#bundled-extensions
says that “namespaces SHOULD be used” and given that this is a
completely new API, I think we should namespace them.My understanding is that the proposed API relies on a file descriptor
and not something like a timeout. It therefore makes sense to me to put
it into anamespace Io\Poll;or similar. We would then also have:namespace Io; class IoException extends \Exception {} namespace Io\Poll; class PollException extends \Io\IoException {}
I thought about this and think this might be a good idea.
Just to note internally it might not always be a fd. For example,
TimerHandle might implement internal API not requiring fd because some
platforms (e.g. kqueue ones) don't use it but from the API design (and on
Linux), it is fd based so putting that to Io namespace might make sense.
The thing is that I also started working on new IO copy API:
https://github.com/php/php-src/compare/master...bukka:php-src:io_copy .
This is just a stub but it aims to introduce new IO layer (initial mainly
for copying but potentially cover more operations) and it should also
contain a new IO ring (on Linux based on io_uring) variant that could be
potentially also exposed in some form. I will get it to some working form
in the coming weeks and then thing how to organise it with the poll.
The StreamPollHandle method should possibly be placed in the global
namespace still, since the stream functions are sitting there - and a
SocketPollHandle would of course be sitting in the namespace of the
Sockets extension.
Yeah those could stay in global and just extend Io\Poll\Handle.
- As for the PollBackend enum.
Is there a reason why this is a backed enum? Generally speaking enums
should not be backed, unless there is a good reason for this. I don't
think there is in this case - and none of the native enums are backed so
far.
I missed that they should not be backed. I just saw enum AdjacentPosition : string in Dom so thought that it's fine to use it... Will change it.
- Exception-wise.
StreamPollHandle::__construct(): This should probably be a ValueError,
not a PollException, since passing an invalid stream is a programmer
error.
This makes sense.
In the other cases it probably makes sense to further split the
PollException into purpose-built exceptions according to the Throwable
policy athttps://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables
(“The exception message MUST NOT be the only means of distinguishing
exception causes that the user might want to handle differently.”).
This makes sense and I will introduce more exceptions. I will not use
exception per errno but some middle ground is a good idea. Maybe per op
exception with codes representing specific errors would be make sense?
As an example PollContext::__construct() should probably throw a
BackendUnavailableException or something like this. For
PollContext::add() I'm wondering in which cases a handle “cannot be
added”.
It fails if the same fd is added. This is also limitation of backends (e.g.
epoll does not allow the same fd to be added twice). I got error code for
the specific errors so this should be probably exposed as well. It would
still make sense to differentiate that it's an exception for addition.
Is this an error situation that users will encounter in the real
world? Similarly, when can PollContext::wait() fail?
Wait might also fail but less likely.
- PollBackend
Is the availability of the backends known at compile time of PHP or at
runtime only? Depending on that it might make sense to only
conditionally define the enum cases, allowing users to check
availability withdefined()or checking the output of::cases().
Alternatively, apublic static function getAvailableBackends(): array
could be added.
It's compile time but not sure if I like exposing enum only if compiled in
as it makes the checks harder. This part is not really something that
users should use but it's really more for testing purpose. In reality
everyone should just use default Auto... But getAvailableBackends() might
make sense even for testing. Maybe it could also have per enum method
isAvailable() so user can check that but not sure if it's needed.
Kind regards,
Jakub
Hi
Apologies for the late reply. It was a few busy weeks leading up to the
PHP 8.5 Release.
When searching for the RFC text I just noticed that it does not appear
to be listed in https://wiki.php.net/rfc#under_discussion yet.
- As for the PollBackend enum.
Is there a reason why this is a backed enum? Generally speaking enums
should not be backed, unless there is a good reason for this. I don't
think there is in this case - and none of the native enums are backed so
far.I missed that they should not be backed. I just saw
enum AdjacentPosition : stringin Dom so thought that it's fine to use it... Will change it.
I missed that one indeed. That one is a little special, because ext/dom
implements an existing API standard, where the API is defined based on
string parameters. So there already was a “well-defined” string for each
enum case that is needed for better interoperability with the external
standard.
In the other cases it probably makes sense to further split the
PollException into purpose-built exceptions according to the Throwable
policy athttps://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables
(“The exception message MUST NOT be the only means of distinguishing
exception causes that the user might want to handle differently.”).This makes sense and I will introduce more exceptions. I will not use
exception per errno but some middle ground is a good idea. Maybe per op
exception with codes representing specific errors would be make sense?
Yes, that makes sense to me. I don't exactly know which types of error
can appear, but as a developer I am generally not interested in
super-granular handling of the errors but rather broad categories. If
the details are only available as the code, then that's totally fine and
within policy.
As an example PollContext::__construct() should probably throw a
BackendUnavailableException or something like this. For
PollContext::add() I'm wondering in which cases a handle “cannot be
added”.It fails if the same fd is added. This is also limitation of backends (e.g.
epoll does not allow the same fd to be added twice). I got error code for
the specific errors so this should be probably exposed as well. It would
still make sense to differentiate that it's an exception for addition.
I see. I was wondering if it would make sense to simply ignore the
error, thus making the operation idempotent (more convenient for a
high-level language like PHP). But I suppose that doesn't work, because
the $data could be different?
Exception-wise this should probably be a DuplicateHandleError (i.e.
within the Error hierarchy, since it's a programming error to add
duplicate handles).
It's compile time but not sure if I like exposing enum only if compiled in
as it makes the checks harder. This part is not really something that
users should use but it's really more for testing purpose. In reality
everyone should just use default Auto... But getAvailableBackends() might
make sense even for testing. Maybe it could also have per enum method
isAvailable() so user can check that but not sure if it's needed.
I'll think about this more when you made a decision and updated the RFC
text :-)
Best regards
Tim Düsterhus
Hi,
Hi
Apologies for the late reply. It was a few busy weeks leading up to the
PHP 8.5 Release.When searching for the RFC text I just noticed that it does not appear
to be listed in https://wiki.php.net/rfc#under_discussion yet.
This is fixed.
As an example PollContext::__construct() should probably throw a
BackendUnavailableException or something like this. For
PollContext::add() I'm wondering in which cases a handle “cannot be
added”.It fails if the same fd is added. This is also limitation of backends
(e.g.
epoll does not allow the same fd to be added twice). I got error code for
the specific errors so this should be probably exposed as well. It would
still make sense to differentiate that it's an exception for addition.I see. I was wondering if it would make sense to simply ignore the
error, thus making the operation idempotent (more convenient for a
high-level language like PHP). But I suppose that doesn't work, because
the$datacould be different?
Yeah data and events can be different.
Exception-wise this should probably be a DuplicateHandleError (i.e.
within the Error hierarchy, since it's a programming error to add
duplicate handles).
I don't think users should be expected to keep track of added handles. So I
think that this is something that can be nicely handled and in some cases
it will be just fine to just catch it and ignore. So I wouldn't see this as
a programmer error and therefore the exception is more appropriate IMHO. I
created a specific exception for this called
\Io\Poll\HandleAlreadyWatchedException so it will be easy for users to
differentiate it.
Kind regards,
Jakub
Hi,
Hi
Am 2025-10-30 22:06, schrieb Jakub Zelenka:
I would like to introduce a new polling API RFC that is part of my
stream
evolution work:
Thank you for the RFC. I've taken a first skim of the proposal and it
immediately raised the question of naming and namespacing in particular.
Our naming policy at
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#bundled-ewill
be alwaysxtensions
https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#bundled-extensions
says that “namespaces SHOULD be used” and given that this is a
completely new API, I think we should namespace them.My understanding is that the proposed API relies on a file descriptor
and not something like a timeout. It therefore makes sense to me to put
it into anamespace Io\Poll;or similar. We would then also have:namespace Io; class IoException extends \Exception {} namespace Io\Poll; class PollException extends \Io\IoException {}I thought about this and think this might be a good idea.
This is implemented as suggested and RFC updated.
The StreamPollHandle method should possibly be placed in the global
namespace still, since the stream functions are sitting there - and a
SocketPollHandle would of course be sitting in the namespace of the
Sockets extension.Yeah those could stay in global and just extend Io\Poll\Handle.
- As for the PollBackend enum.
Is there a reason why this is a backed enum? Generally speaking enums
should not be backed, unless there is a good reason for this. I don't
think there is in this case - and none of the native enums are backed so
far.I missed that they should not be backed. I just saw
enum AdjacentPosition : stringin Dom so thought that it's fine to use it... Will change it.
This is also fixed and it's no longer a backed enum.
- Exception-wise.
StreamPollHandle::__construct(): This should probably be a ValueError,
not a PollException, since passing an invalid stream is a programmer
error.This makes sense.
In the other cases it probably makes sense to further split the
PollException into purpose-built exceptions according to the Throwable
policy athttps://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables
(“The exception message MUST NOT be the only means of distinguishing
exception causes that the user might want to handle differently.”).This makes sense and I will introduce more exceptions. I will not use
exception per errno but some middle ground is a good idea. Maybe per op
exception with codes representing specific errors would be make sense?
I created a new exception hierarchy that is hopefully in line
with Throwable policy.
As an example PollContext::__construct() should probably throw a
BackendUnavailableException or something like this.
There are now getAvailableBackends so users should check it out before so I
used ValueError for this part.
- PollBackend
Is the availability of the backends known at compile time of PHP or at
runtime only? Depending on that it might make sense to only
conditionally define the enum cases, allowing users to check
availability withdefined()or checking the output of::cases().
Alternatively, apublic static function getAvailableBackends(): array
could be added.It's compile time but not sure if I like exposing enum only if compiled in
as it makes the checks harder. This part is not really something that
users should use but it's really more for testing purpose. In reality
everyone should just use default Auto... But getAvailableBackends() might
make sense even for testing. Maybe it could also have per enum method
isAvailable() so user can check that but not sure if it's needed.
Added getAvailableBackends(), isAvailable() and supportsEdgeTriggering()
methods.
Kind regards,
Jakub
Hi Jakub,
Am 30.10.25 um 10:06 PM schrieb Jakub Zelenka:
I would like to introduce a new polling API RFC that is part of my
stream evolution work:
thank you for putting this RFC forward. I missed a build-in unified
polling API for a long time!
I just have some minor remarks:
- Why not use a "Pollable" interface that will be implemented by
Socket, CurlHandle, etc? That would allow to directly use the "resource
classes" without a step in between.
(The remaining resources should be converted to classes, too, and
implement Pollable, obviously).
- Is there a reason why mysqli (when using async queries) is missing
from the Future Scope list? Or did it just not come to mind?
Kind regards
Dennis
Hi,
On Fri, Oct 31, 2025 at 11:58 PM Dennis Birkholz php@dennis.birkholz.biz
wrote:
- Why not use a "Pollable" interface that will be implemented by
Socket, CurlHandle, etc? That would allow to directly use the "resource
classes" without a step in between.
I actually planned to use interface initially but there are few issue with
it.
- as I mentioned above, not all handles will always allow using file
descriptors (e.g. timer for kqueue) - abstract class allow internal api defintion and not calling the PHP
functions internally (that's how the above can be handled as well) - it would require exposing the actual fd numbers for streams which after
some thinking might not be best idea because it would make easier for
people to have two streams for a single fd which might cause issues with
filtering, buffering and so on.
- Is there a reason why mysqli (when using async queries) is missing
from the Future Scope list? Or did it just not come to mind?
I put there just those that I actually plan to implement and are relatively
straight forward. For mysqli it might require some abstraction to get the
mysqlnd stream so would need to check it out first. In other words I
haven't fully investigated it yet. But it should be probably added too.
Kind regards,
Jakub
Hello,
I would like to introduce a new polling API RFC that is part of my
stream evolution work:https://wiki.php.net/rfc/poll_api
Kind regards,
Jakub
I freely admit to not being fully versed in this area, so take my feedback with however much sodium chloride you feel is appropriate.
-
Given that a lot of people reading this are probably no more versed in kernel IO polling than I am, a section early on explaining the context of what is even being discussed would be most appreciated.
-
I really would rather not add more global constants. Better to at minimum make them class constants of a class that the new API provides. (Maybe PollHandle?)
-
Conversely, I'm unclear why the PollBackend is an enum. That implies the list of backend implementations is fixed and immutable, and not extensible now or in the future. I find that claim suspect, as there are six already. (I find that following the 0-1-many rule in most cases pays off in the long run.)
-
PollWatcher is created only by PollContext. OK, then please list PollContext first so that reading PollWatcher I have the, er, context for where it fits.
-
Speaking of, when there's very long code blocks like this I much prefer to break it up to a block per class, so as to minimize codeblock scrolling. That makes it much easier to read and jump around as I figure out how it all works.
-
How would requesting a specific poll backend be helpful, if it varies by OS? If I'm running on Windows, asking for the Linux backend wouldn't help me much, or vice versa. I don't see the use case here. (Ie, please describe the use case in more detail.)
-
Who is the target audience for this? I'm pretty sure it's not anything I normally work on, so it's hard for me to judge if certain decisions are good, bad, or "sucky but we have to." Eg, getData() returning "who the hell knows" strikes me as a footgun in waiting, but I don't have enough context to know if that's an inherited problem from elsewhere.
Overall, I think my biggest feedback is "please explain better why any of this matters, because I assume it does somehow but don't understand how from the RFC."
--Larry Garfield
I don't know what changes this proposal could bring to PHP if the aim is simply to introduce event loop mechanisms like epoll or kqueue.
Why not make ext-uv (libuv) or ext-event (libev) built-in PHP extensions, just like ext-curl, ext-xml, or ext-bcmath?
These event loop libraries have been thoroughly tested across numerous projects, proving to be extremely stable and reliable. They could serve as the foundational infrastructure for implementing asynchronous IO in PHP.
Tianfeng.Han
------------------ Original ------------------
From: "Larry Garfield";
Date: 2025年11月2日(星期天) 凌晨3:24
To: "php internals";
Subject: Re: [PHP-DEV] [RFC] Polling API
> Hello,
>
> I would like to introduce a new polling API RFC that is part of my
> stream evolution work:
>
> https://wiki.php.net/rfc/poll_api
>
> Kind regards,
>
> Jakub
I freely admit to not being fully versed in this area, so take my feedback with however much sodium chloride you feel is appropriate.
-
Given that a lot of people reading this are probably no more versed in kernel IO polling than I am, a section early on explaining the context of what is even being discussed would be most appreciated.
-
I really would rather not add more global constants. Better to at minimum make them class constants of a class that the new API provides. (Maybe PollHandle?)
-
Conversely, I'm unclear why the PollBackend is an enum. That implies the list of backend implementations is fixed and immutable, and not extensible now or in the future. I find that claim suspect, as there are six already. (I find that following the 0-1-many rule in most cases pays off in the long run.)
-
PollWatcher is created only by PollContext. OK, then please list PollContext first so that reading PollWatcher I have the, er, context for where it fits.
-
Speaking of, when there's very long code blocks like this I much prefer to break it up to a block per class, so as to minimize codeblock scrolling. That makes it much easier to read and jump around as I figure out how it all works.
-
How would requesting a specific poll backend be helpful, if it varies by OS? If I'm running on Windows, asking for the Linux backend wouldn't help me much, or vice versa. I don't see the use case here. (Ie, please describe the use case in more detail.)
-
Who is the target audience for this? I'm pretty sure it's not anything I normally work on, so it's hard for me to judge if certain decisions are good, bad, or "sucky but we have to." Eg, getData() returning "who the hell knows" strikes me as a footgun in waiting, but I don't have enough context to know if that's an inherited problem from elsewhere.
Overall, I think my biggest feedback is "please explain better why any of this matters, because I assume it does somehow but don't understand how from the RFC."
--Larry Garfield
Hi,
First of all, please don't top post.
I don't know what changes this proposal could bring to PHP if the aim is
simply to introduce event loop mechanisms like epoll or kqueue.
The primary reason for this is to have an internal API that we can use
internally. The primary motivation was to actually have a better mechanism
for handling signals that can be safely used in ZTS. This is one of the
main blocker for introducing coroutine based TSRM mode that could be used
by FrankenPHP to use goroutines instead of threads. There was also related
timer issue on MacOS and at that time Arnaud came up with kqueue only PoC
implentation but we decided that it would be great to have something more
generic but we wanted something really minimal without a need for the whole
event loop abstraction like libuv or libevent (libev is dead AFAIC) offers.
After that I also had few other use cases in FPM as I wanted a bit more
generic event handling than what is currently there so I can use it in
child before accept. Note that we have got already its own event
implementation in FPM so this is more advancement in that area.
So when we have an internal API which we plan anyway, then I thought it
could be nice to also expose it to user space so project like AMPHP can use
it and effectively drop all other backends. In addition it didn't look good
that the only current polling mechanism for streams is based on select so
this is also effectively replacement for stream_select. Again not all users
using it need the full even loop.
Why not make ext-uv (libuv) or ext-event (libev) built-in PHP extensions,
just like ext-curl, ext-xml, or ext-bcmath?
Those are all optional extensions because they depend on external library.
Currently the only way how we could make it always available is to bundle
those libraries but especially libuv is quite bloated and adds unnecessary
overhead for our other use cases. We actually discussed it internally if we
should use or bundled libevent but the agreement between couple of core
devs was to create a simple polling API instead so here we are.
I will update the RFC and add more explanation there as this was also
requested by Larry and I can see that the motivation and primary use cases
for this are not exactly clear.
Thanks for the feedback.
Kind regards,
Jakub
Hi,
On Sat, Nov 1, 2025 at 8:23 PM Larry Garfield larry@garfieldtech.com
wrote:
Hello,
I would like to introduce a new polling API RFC that is part of my
stream evolution work:https://wiki.php.net/rfc/poll_api
Kind regards,
Jakub
I freely admit to not being fully versed in this area, so take my feedback
with however much sodium chloride you feel is appropriate.
- Given that a lot of people reading this are probably no more versed in
kernel IO polling than I am, a section early on explaining the context of
what is even being discussed would be most appreciated.
I added a section with some basic explanation so users that are more
interested in details can easily search for it.
- I really would rather not add more global constants. Better to at
minimum make them class constants of a class that the new API provides.
(Maybe PollHandle?)
I replaced them with \Io\Poll\Event enum so this should be covered. There
are no global constants. The only constants are now on class and they are
for error codes.
- Conversely, I'm unclear why the PollBackend is an enum. That implies
the list of backend implementations is fixed and immutable, and not
extensible now or in the future. I find that claim suspect, as there are
six already. (I find that following the 0-1-many rule in most cases pays
off in the long run.)
This is unlikely to grow and if it ever grew, it would happen only as a new
feature in new minor version. Or do we have any policy that disallows
extending enums? This is just a theoretical concern though because all the
main backends are covered. The only one that could be potentially added is
a different variant for Windows if WSAPoll shows poor performance as it was
the case in past but not sure if anyone will do such work.
- PollWatcher is created only by PollContext. OK, then please list
PollContext first so that reading PollWatcher I have the, er, context for
where it fits.
Updated.
- Speaking of, when there's very long code blocks like this I much prefer
to break it up to a block per class, so as to minimize codeblock
scrolling. That makes it much easier to read and jump around as I figure
out how it all works.
Fixed.
- How would requesting a specific poll backend be helpful, if it varies by
OS? If I'm running on Windows, asking for the Linux backend wouldn't help
me much, or vice versa. I don't see the use case here. (Ie, please
describe the use case in more detail.)
There is poll supported on all unix variants and then Illumos has also
variant of epoll so there are more than one backend for each platform
(except Windows that currently support just one). As noted in the RFC,
setting of the backend is mostly useful for testing. The actual enum is
more useful to get info of the selected backend. Currently the most useful
thing is to find out whether edge triggering is possible.
- Who is the target audience for this? I'm pretty sure it's not anything
I normally work on, so it's hard for me to judge if certain decisions are
good, bad, or "sucky but we have to." Eg, getData() returning "who the
hell knows" strikes me as a footgun in waiting, but I don't have enough
context to know if that's an inherited problem from elsewhere.
Added a section explaining the motivation and possible users of this API.
In terms of getData, we would need to have generics to make it typed as
this is for user data. You can see the examples that should give you
hopefully some idea how this can be used.
Kind regards,
Jakub
I would like to introduce a new polling API RFC that is part of my
stream evolution work:
Under "Event Constants", I realised that we can't use enums for this
due to them needing to be OR'ed, but it would be nice if at some point
in the future we had a way of doing: PollEvent::Read | PollEvent::Write;
The enum PollBackend (not sure if that needs to be a backed enum), but
this can not stand:
case EventPorts = "eventport";
All the others have the case name and value the same, but this one
misses the 's'.
/**
* Remove this watcher from the poll context
*
* After removal, the watcher becomes inactive and cannot be reused.
*/
public function remove(): void {}
Wouldn't this leave the PollWatcher object as a zombie: ie, it exists,
but you can't do anything with it. Would it be possible to move this API
somewhere else, so that the memory manager can just destruct it and
release the object?
* @param int $maxEvents Maximum number of events to return (-1 for unlimited)
* @return array Array of PollWatcher instances that have triggered events
* @throws PollException If the wait operation fails
*/
public function wait(int $timeout = -1, int $maxEvents = -1): array {}
I am not sure if I like this returning an array. Would it perhaps be
better to always return 1 (or 0 in case of non-blocking) events, which
allows typing the return value as ?PollWatcher?
Alternative, perhaps this can be split up into two methods, wait() and
waitMultiple() to be able to handle both approaches?
Under "Future Scope", you have (for example) TimerHandle, but as that
will (have to) extend PollHandle, it makes little sense to have a
getFileDescriptor() method on PollHandle. Perhaps there should be
another (abstract) class, so that you can have:
- PollHandle
- FileDescriptorPollHandle
- StreamPollHandle
- SocketPollHandle
- CurlPollHandle
- TimerPollHandle
- SignalPollHandle
- FileDescriptorPollHandle
The only other concern I have is that some polling backends allow for
different events to be watched, which makes it harder to write portable
code.
cheers,
Derick
--
https://derickrethans.nl | https://xdebug.org | https://dram.io
Author of Xdebug. Like it? Consider supporting me: https://xdebug.org/support
mastodon: @derickr@phpc.social @xdebug@phpc.social
Hi,
I would like to introduce a new polling API RFC that is part of my
stream evolution work:Under "Event Constants", I realised that we can't use enums for this
due to them needing to be OR'ed, but it would be nice if at some point
in the future we had a way of doing: PollEvent::Read | PollEvent::Write;
I introduce \Io\Poll\Event enum. It doesn't allow ORing but all functions
now accept array of those events which is hopefully good enough and cover
this. If we ever introduced something like enum sets supporting OR
operator, the functions could accept it in addition to the array.
The enum PollBackend (not sure if that needs to be a backed enum), but
this can not stand:case EventPorts = "eventport";All the others have the case name and value the same, but this one
misses the 's'.
It's no longer a backed enum so this is sorted.
/** * Remove this watcher from the poll context * * After removal, the watcher becomes inactive and cannot be reused. */ public function remove(): void {}Wouldn't this leave the PollWatcher object as a zombie: ie, it exists,
but you can't do anything with it. Would it be possible to move this API
somewhere else, so that the memory manager can just destruct it and
release the object?
The PollWatcher was introduced on request from Bob so the new objects are
not created after each polling. This should be more efficient but to be
able to remove it, it needs to be done explicitly because the reference is
held so we need to somehow inform context that it can be removed. I think
we could introduce API to re-use it in the future but for now leaving clean
up to GC is the way.
Btw. there isActive() method that still works after removal and it returns
false. The modification method will throw exception if used.
If you have some suggestion for better API, I will be happy to consider it.
* @param int $maxEvents Maximum number of events to return (-1 forunlimited)
* @return array Array of PollWatcher instances that have triggered
events
* @throws PollException If the wait operation fails
*/
public function wait(int $timeout = -1, int $maxEvents = -1): array {}I am not sure if I like this returning an array. Would it perhaps be
better to always return 1 (or 0 in case of non-blocking) events, which
allows typing the return value as ?PollWatcher?
Returning just a single event is not ideal for performance if there are
many events so not sure it should be the preferred usage of the API.
Alternative, perhaps this can be split up into two methods, wait() and
waitMultiple() to be able to handle both approaches?
I would see it more like introducing waitSingle but it's basically just
public function waitSingle(int $timeout = -1): ?PollWatcher {
return $this->wait($timeout, 1)[0] ?? null;
}
so not sure if it's that useful. But if you think, it's worth it, I can add
it..?
Under "Future Scope", you have (for example) TimerHandle, but as that
will (have to) extend PollHandle, it makes little sense to have a
getFileDescriptor() method on PollHandle.
The timer and signal are actually file descriptors on Linux (timerfd and
signalfd) but you are right that this is not always the case. This is
however internal and that abstract class offers a different API for
internal extending that is more flexible. It means it won't
call getFileDescriptor() for internal classes but use direct C API.
That getFileDescriptor() is really meant for user classes that
extend PollHandle so they do something rather than extending class with
empty interface.
Perhaps there should be
another (abstract) class, so that you can have:
- PollHandle
- FileDescriptorPollHandle
- StreamPollHandle
- SocketPollHandle
- CurlPollHandle
- TimerPollHandle
- SignalPollHandle
So in this case I think I would need to come up with some different way how
to allow polling without file descriptor for user classes otherwise user
space class could extend PollHandle and it would just do nothing which I
don't think is the right thing. I thought about it and I just don't have
any idea what that could be. I think that non fd variants don't make much
sense for user space or at least I don't see any reasonable use case.
The only other concern I have is that some polling backends allow for
different events to be watched, which makes it harder to write portable
code.
I tried to make it as portable as possible but edge triggering is just not
possible to simulate and I think it's worth exposing it even though it
doesn't work on Windows and Solaris. I added at least flag in the backend
so it's quite simple to check.
Kind regards,
Jakub