diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-05-22 08:38:37 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-05-22 08:38:37 +0000 |
commit | 13ddc9fdd0317694352672ac8e5e8b8482cd4e6b (patch) | |
tree | 33bf888d0b7218f797f0a5d131788b793fc7dce5 /io.c | |
parent | db3bdf6eca24d6f78fbf29c8c22751aca5316c29 (diff) |
* rubyio.h (rb_io_set_nonblock): declared.
* io.c (rb_io_set_nonblock): new function.
(io_getpartial): nonblocking read support.
(io_read_nonblock): new method: IO#read_nonblock.
(io_write_nonblock): new method: IO#write_nonblock.
* ext/socket/socket.c
(sock_connect_nonblock): new method: Socket#connect_nonblock.
(sock_accept_nonblock): new method: Socket#accept_nonblock.
(sock_recvfrom_nonblock): new method: Socket#recvfrom_nonblock.
[ruby-core:7917]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10176 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 130 |
1 files changed, 123 insertions, 7 deletions
@@ -1185,8 +1185,39 @@ read_all(fptr, siz, str) return str; } +void rb_io_set_nonblock(OpenFile *fptr) +{ + int flags; +#ifdef F_GETFL + flags = fcntl(fileno(fptr->f), F_GETFL); + if (flags == -1) { + rb_sys_fail(fptr->path); + } +#else + flags = 0; +#endif + flags |= O_NONBLOCK; + if (fcntl(fileno(fptr->f), F_SETFL, flags) == -1) { + rb_sys_fail(fptr->path); + } + if (fptr->f2) { +#ifdef F_GETFL + flags = fcntl(fileno(fptr->f2), F_GETFL); + if (flags == -1) { + rb_sys_fail(fptr->path); + } +#else + flags = 0; +#endif + flags |= O_NONBLOCK; + if (fcntl(fileno(fptr->f2), F_SETFL, flags) == -1) { + rb_sys_fail(fptr->path); + } + } +} + static VALUE -io_getpartial(int argc, VALUE *argv, VALUE io) +io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock) { OpenFile *fptr; VALUE length, str; @@ -1214,7 +1245,9 @@ io_getpartial(int argc, VALUE *argv, VALUE io) if (len == 0) return str; - READ_CHECK(fptr->f); + if (!nonblock) { + READ_CHECK(fptr->f); + } if (RSTRING(str)->len != len) { modified: rb_raise(rb_eRuntimeError, "buffer string modified"); @@ -1223,11 +1256,17 @@ io_getpartial(int argc, VALUE *argv, VALUE io) if (n <= 0) { again: if (RSTRING(str)->len != len) goto modified; - TRAP_BEG; - n = read(fileno(fptr->f), RSTRING(str)->ptr, len); - TRAP_END; + if (nonblock) { + rb_io_set_nonblock(fptr); + n = read(fileno(fptr->f), RSTRING(str)->ptr, len); + } + else { + TRAP_BEG; + n = read(fileno(fptr->f), RSTRING(str)->ptr, len); + TRAP_END; + } if (n < 0) { - if (rb_io_wait_readable(fileno(fptr->f))) + if (!nonblock && rb_io_wait_readable(fileno(fptr->f))) goto again; rb_sys_fail(fptr->path); } @@ -1302,7 +1341,7 @@ io_readpartial(int argc, VALUE *argv, VALUE io) { VALUE ret; - ret = io_getpartial(argc, argv, io); + ret = io_getpartial(argc, argv, io, 0); if (NIL_P(ret)) rb_eof_error(); else @@ -1311,6 +1350,81 @@ io_readpartial(int argc, VALUE *argv, VALUE io) /* * call-seq: + * ios.read_nonblock(maxlen) => string + * ios.read_nonblock(maxlen, outbuf) => outbuf + * + * Reads at most <i>maxlen</i> bytes from <em>ios</em> using + * read(2) system call after O_NONBLOCK is set for + * the underlying file descriptor. + * + * If the optional <i>outbuf</i> argument is present, + * it must reference a String, which will receive the data. + * + * read_nonblock just calls read(2). + * It causes all errors read(2) causes: EAGAIN, EINTR, etc. + * The caller should care such errors. + * + * read_nonblock causes EOFError on EOF. + * + * If the read buffer is not empty, + * read_nonblock reads from the buffer like readpartial. + * In this case, read(2) is not called. + * + */ + +static VALUE +io_read_nonblock(int argc, VALUE *argv, VALUE io) +{ + VALUE ret; + + ret = io_getpartial(argc, argv, io, 1); + if (NIL_P(ret)) + rb_eof_error(); + else + return ret; +} + +/* + * call-seq: + * ios.write_nonblock(string) => integer + * + * Writes the given string to <em>ios</em> using + * write(2) system call after O_NONBLOCK is set for + * the underlying file descriptor. + * + * write_nonblock just calls write(2). + * It causes all errors write(2) causes: EAGAIN, EINTR, etc. + * The result may also be smaller than string.length (partial write). + * The caller should care such errors and partial write. + * + */ + +static VALUE +rb_io_write_nonblock(VALUE io, VALUE str) +{ + OpenFile *fptr; + FILE *f; + long n; + + rb_secure(4); + if (TYPE(str) != T_STRING) + str = rb_obj_as_string(str); + + GetOpenFile(io, fptr); + rb_io_check_writable(fptr); + + f = GetWriteFile(fptr); + + rb_io_set_nonblock(fptr); + n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len); + + if (n == -1) rb_sys_fail(fptr->path); + + return LONG2FIX(n); +} + +/* + * call-seq: * ios.read([length [, buffer]]) => string, buffer, or nil * * Reads at most <i>length</i> bytes from the I/O stream, or to the @@ -5663,6 +5777,8 @@ Init_IO() rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1); + rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1); + rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1); rb_define_method(rb_cIO, "readpartial", io_readpartial, -1); rb_define_method(rb_cIO, "read", io_read, -1); rb_define_method(rb_cIO, "write", io_write, 1); |