IO::Select extension

X

xhoster

IO::Select does a nice job of hiding the ugliness of 'select'. But
it warns that it shouldn't be mixed with buffered I/O, which still leaves
me to deal with all the messy sysread and syswrite stuff. I've been
thinking lately of making a module that would either subclass or contain
IO::Select objects and give them the veneer of being buffered IO rather
than unbuffered IO. Have I overlooked something already in CPAN that does
this? Am I insane for thinking this is desirable and/or possible?

Thanks,

Xho
 
B

Brian McCauley

IO::Select does a nice job of hiding the ugliness of 'select'. But
it warns that it shouldn't be mixed with buffered I/O, which still leaves
me to deal with all the messy sysread and syswrite stuff. I've been
thinking lately of making a module that would either subclass or contain
IO::Select objects and give them the veneer of being buffered IO rather
than unbuffered IO. Have I overlooked something already in CPAN that does
this? Am I insane for thinking this is desirable and/or possible?

I have often thought about this but have never done anything about it.

There is a problem. If you want to avoid the need to play with sysread
then you need to find a way to allow read() or readline() not to block
when there is insufficient data avialable to satisfy them.

To do this all the handles returned by IO::Select would have to be
wrapped in a special class that simulates read()/readline() using
sysread() and return undef with $!=EAGAIN when there's insufficient data.

Then you have to find a way to avoid a busy loop when there is data in
the buffer but not enough to satisfy the read() or readline(). One way
to do this would be to make an unsatisfied read()/readline() set a flag
to say that even though there is data in the buffer that the special
buffered IO::Select must not report that the handle is readable.

On the write side you need and extra layer of buffering to set a
threshold and tell the buffered IO::Select only to return a handle as
writable if there is at least that much space in the buffer.

As you can see I've given this a little thought.
 
X

xhoster

Brian McCauley said:
I have often thought about this but have never done anything about it.

There is a problem. If you want to avoid the need to play with sysread
then you need to find a way to allow read() or readline() not to block
when there is insufficient data avialable to satisfy them.

To do this all the handles returned by IO::Select would have to be
wrapped in a special class that simulates read()/readline() using
sysread() and return undef with $!=EAGAIN when there's insufficient data.

My ideas was to keep the interface as close to IO::Select as possible,
so can_read would return handles that would not block upon (a
single) readline. If someone were foolish enough to call readline on a
handle not returned by can_read, then just let them block. That way you
don't need to screw around with EAGAIN.

But this would still require the handle to be wrapped in a special class,
which means the handle returned by can_read would not test identical to the
handle that was passed in to the selector class in the first place, so this
would still break the analogy to IO::Select.

Once I decided that I can't keep highly analogous to IO::Select, I started
wondering why even have can_read(). If the module knows the complete line
can be read, rather than returning a flag, return the line itself. So you
would have do_read(), which would return a hashref where keys are
filehandles and values are the corresponding lines that were read for those
handles. But them I wonder if I haven't digressed from a IO::Select-like
module into a full message passing module.
Then you have to find a way to avoid a busy loop when there is data in
the buffer but not enough to satisfy the read() or readline(). One way
to do this would be to make an unsatisfied read()/readline() set a flag
to say that even though there is data in the buffer that the special
buffered IO::Select must not report that the handle is readable.

I think that that is about what I was thinking. The hardest part would be
the timeouts. If the system-level select comes back with a sysread-able
handle, you sysread it into a internal buffer. But if that was not enough
to make a full record, then you should to re-start the system-level select
with a new timeout which is the old timeout minus the time spent in the
prior select. But I guess most systems don't reliably report the info
needed to compute this. Of course, you could probably just return early
(with an empty readable list/hash) in this case.
On the write side you need and extra layer of buffering to set a
threshold and tell the buffered IO::Select only to return a handle as
writable if there is at least that much space in the buffer.

I would use a dynamically resizable internal write buffer, then have
can_write report handles that are under some in-use buffer-space threshold,
rather than have it report handles that are over some free buffer-space
threshold. And if they keep writing to a handle even though it is no longer
"writable" by that threshold, there is no blocking and no problem as long
as they have enough RAM to keep expanding the buffer.

As you can see I've given this a little thought.

Me too. But now I'm wondering if my time wouldn't be better spent just
learning Event.pm or something like that rather than rewriting IO::Select.

Xho
 
T

Tassilo v. Parseval

Also sprach (e-mail address removed):
Brian McCauley <[email protected]> wrote:

[ select(2) with buffered I/O ]
My ideas was to keep the interface as close to IO::Select as possible,
so can_read would return handles that would not block upon (a
single) readline. If someone were foolish enough to call readline on a
handle not returned by can_read, then just let them block. That way you
don't need to screw around with EAGAIN.

But this would still require the handle to be wrapped in a special class,
which means the handle returned by can_read would not test identical to the
handle that was passed in to the selector class in the first place, so this
would still break the analogy to IO::Select.

How about overloading the '==' operator?

Tassilo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
ScottChare

Latest Threads

Top