なかだです。


At Sat, 7 Feb 2004 00:15:03 +0900,
Ara.T.Howard wrote in [ruby-talk:91705]:
> > > why not have it in the core io methods?
> > 
> > Well, IIRC, because it is not portable enough, for io/wait at least.  Hmmm,
> > but EWOULDBLOCK is supported by core..., might it be OK for io/nonblock
> > alone?
> 
> i don't really know - i was just saying that is it such a useful method it
> would be nice if it were possible for it to be in the core.

IO#nonblockというメソッドを、なぜかio/waitに入れてしまったんで
すが、考えてみるとio/waitとは関係なさそうです。そもそも、すでに
O_NONBLOCKはEAGAINと一緒にio.cで対応済みなので、必要なのはイン
ターフェースだけではないかと思うのですが。

  IO#nonblock?
  IO#nonblock = nb
  IO#nonblocking([nb = true]) {}
  IO#nonblock {}
  IO#nonblock

あたりでどうかと。


Index: io.c =================================================================== RCS file: /cvs/ruby/src/ruby/io.c,v retrieving revision 1.258 diff -u -2 -p -d -r1.258 io.c --- io.c 26 Jan 2004 13:54:29 -0000 1.258 +++ io.c 12 Feb 2004 03:38:49 -0000 @@ -4496,4 +4496,139 @@ rb_io_fcntl(argc, argv, io) } +#ifndef O_NONBLOCK +# ifdef O_NDELAY +# define O_NONBLOCK O_NDELAY +# endif +#endif + +/* + * call-seq: + * ios.nonblock? => true or false + * + * Returns true if _ios_ is in non-blocking mode. + * + * f = File.new("/dev/tty", IO::RDONLY|IO::NONBLOCK) + * f.nonblock? #=> true + */ + +static VALUE +rb_io_nonblock_p(io) + VALUE io; +{ +#if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK) + OpenFile *fptr; + int flag; + + GetOpenFile(io, fptr); + if ((flag = fcntl(fileno(fptr->f), F_GETFL)) == -1) { + rb_sys_fail(0); + } + if (flag & O_NONBLOCK) return Qtrue; +#endif + return Qfalse; +} + +/* + * call-seq: + * ios.nonblock = nb + * + * Sets non-blocking mode of _ios_ to _nb_. + */ + +static VALUE +rb_io_set_nonblock(io, nb) + VALUE io, nb; +{ +#if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK) + OpenFile *fptr; + int fd, flag, newflag; + VALUE ret; + + GetOpenFile(io, fptr); + fd = fileno(fptr->f); + if ((flag = fcntl(fd, F_GETFL)) == -1) { + rb_sys_fail(0); + } + if (RTEST(nb)) { + newflag = flag | O_NONBLOCK; + ret = Qfalse; + } + else { + newflag = flag & ~O_NONBLOCK; + ret = Qtrue; + } + if (flag != newflag) { + if (fcntl(fd, F_SETFL, newflag)) + rb_sys_fail(0); + return ret; + } +#else + rb_notimplement(); +#endif + return Qnil; +} + +static VALUE +io_restore_flag(args) + int *args; +{ + return rb_io_set_nonblock(args[0], args[1]); +} + +/* + * call-seq: + * ios.nonblocking([nb = true]) { block } => obj + * + * Yields the given block setting non-blocking mode of _ios_ to _nb_. + * The mode will be restored when the block terminates. + */ + +static VALUE +rb_io_nonblocking(argc, argv, io) + int argc; + VALUE *argv; + VALUE io; +{ +#if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK) + VALUE nb, args[2]; + + if (rb_scan_args(argc, argv, "01", &nb) == 0) nb = Qtrue; + nb = rb_io_set_nonblock(io, nb); + if (NIL_P(nb)) return rb_yield(Qundef); + args[0] = io; + args[1] = nb; + return rb_ensure(rb_yield, Qundef, io_restore_flag, (VALUE)args); +#else + rb_notimplement(); + return Qnil; /* not reached */ +#endif +} + +/* + * call-seq: + * ios.nonblock => true or false + * ios.nonblock([nb = true]) { block } => obj + * + * If a block is given, same as IO#nonblocking, otherwise same as + * IO#nonblock?. + */ + +static VALUE +rb_io_nonblock(argc, argv, io) + int argc; + VALUE *argv; + VALUE io; +{ + if (rb_block_given_p()) { + return rb_io_nonblocking(argc, argv, io); + } + else { + if (argc > 0) + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); + return rb_io_nonblock_p(io); + } +} + + /* * call-seq: @@ -5322,4 +5457,8 @@ Init_IO() rb_define_method(rb_cIO, "pid", rb_io_pid, 0); rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0); + rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0); + rb_define_method(rb_cIO, "nonblock=", rb_io_set_nonblock, 1); + rb_define_method(rb_cIO, "nonblocking", rb_io_nonblocking, -1); + rb_define_method(rb_cIO, "nonblock", rb_io_nonblock, -1); rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO); @@ -5403,10 +5542,6 @@ Init_IO() rb_file_const("CREAT", INT2FIX(O_CREAT)); rb_file_const("EXCL", INT2FIX(O_EXCL)); -#if defined(O_NDELAY) || defined(O_NONBLOCK) -# ifdef O_NONBLOCK +#ifdef O_NONBLOCK rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK)); -# else - rb_file_const("NONBLOCK", INT2FIX(O_NDELAY)); -# endif #endif rb_file_const("TRUNC", INT2FIX(O_TRUNC));
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦