Misc #12013

io/wait: allow to wait on readable and writable

Added by chucke (Tiago Cardoso) over 4 years ago. Updated over 4 years ago.



If I have a socket and I want to wait for both read and write events, is my only co-pilot:[mysock],[mysock])

the beautiful thing about the #wait_readable and #wait_writable methods is that I can have a friendlier way to compose sockets for other event loops which monkey-patching One example is celluloid-io, which has its own wrappers around the network sockets classes.

But I think there is a limitation when I want to listen for both reads and writes. See both examples below:[mysock],[mysock], nil, 30)
# as opposed to
require 'io/wait'
mysock.wait_readable(30) && mysock.wait_writable(30)

in the second example, I can wait potentially 60 seconds, instead of the 30 from the first example.

I'm not sure which API it should be, my main reference is the celluloid io reactor api in this case:


drawback: there is already a wait method, so backwards compatibility would be gone. or would it? Current arity is 0, which means, one could still alias it to #wait_readable if no argument is passed.

Updated by nobu (Nobuyoshi Nakada) over 4 years ago

  • Description updated (diff)
  • Status changed from Open to Feedback
  • Assignee set to nobu (Nobuyoshi Nakada)

What about:

mysock.wait(30, to: [:read, :write])


mysock.wait(30, to: :readwrite)

Updated by chucke (Tiago Cardoso) over 4 years ago

If the option would be for more verbosity, I'd opt for :readable and :writable, but tell me what you think that it's more readable:

socket.wait(:readable, writable)
socket.wait(:read, write)

socket.wait([:readable, writable]) # allocates one array

There are a lot of alternatives, I'd go for less verbosity (:r, :w, :rw), but don't have a strong opinion about the best API.


Updated by nobu (Nobuyoshi Nakada) over 4 years ago

  • Status changed from Feedback to Closed

Applied in changeset r53642.

wait readable/writable

  • ext/io/wait/wait.c (io_wait_readwrite): [EXPERIMENTAL] allow to wait for multiple modes, readable and writable, at once. the arguments may change in the future. [Feature #12013]

Updated by normalperson (Eric Wong) over 4 years ago

Regarding r53642, how about we limit the symbols to just :r/:w/:rw?

Fewer ways to accomplish the same thing reduces cognitive overhead
for code reviewers; and smaller object size helps everyone.

--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -172,30 +172,12 @@ wait_mode_sym(VALUE mode)
     if (mode == ID2SYM(rb_intern("r"))) {
    return RB_WAITFD_IN;
-    if (mode == ID2SYM(rb_intern("read"))) {
-   return RB_WAITFD_IN;
-    }
-    if (mode == ID2SYM(rb_intern("readable"))) {
-   return RB_WAITFD_IN;
-    }
     if (mode == ID2SYM(rb_intern("w"))) {
    return RB_WAITFD_OUT;
-    if (mode == ID2SYM(rb_intern("write"))) {
-   return RB_WAITFD_OUT;
-    }
-    if (mode == ID2SYM(rb_intern("writable"))) {
-   return RB_WAITFD_OUT;
-    }
     if (mode == ID2SYM(rb_intern("rw"))) {
-    if (mode == ID2SYM(rb_intern("read_write"))) {
-    }
-    if (mode == ID2SYM(rb_intern("readable_writable"))) {
-    }
     rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
     return 0;

I even prefer just supporting wait(:rw) since we already have
"wait_readable"/"wait_writable" methods, but :r and :w may make
sense for consistency.

Updated by chucke (Tiago Cardoso) over 4 years ago

Agreeing with Eric Wong, but apart from that, awesome! Thx Nobu! :)

Updated by chucke (Tiago Cardoso) over 4 years ago

nobu (Nobuyoshi Nakada), I was thinking whether this shouldn't be extended to the #ready? method. This by default checks whether the descriptor has something to read, but I saw that the source code calls the internal C method rb_io_check_readable. Since there is already a method rb_io_check_writable, wouldn't it make sense to make the #ready method receive an argument? (:r/:w/:rw or :read/:write/:readwrite depending of the final API).

I'd open a new issue if I get your approval.

Also available in: Atom PDF