ext/io/nonblock/nonblock.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   io/wait.c -
00004 
00005   $Author: zzak $
00006   created at: Tue Jul 14 21:53:18 2009
00007 
00008   All the files in this distribution are covered under the Ruby's
00009   license (see the file COPYING).
00010 
00011 **********************************************************************/
00012 
00013 #include "ruby.h"
00014 #include "ruby/io.h"
00015 #ifdef HAVE_UNISTD_H
00016 #include <unistd.h>
00017 #endif
00018 #include <fcntl.h>
00019 
00020 #ifdef F_GETFL
00021 static int
00022 io_nonblock_mode(int fd)
00023 {
00024     int f = fcntl(fd, F_GETFL);
00025     if (f == -1) rb_sys_fail(0);
00026     return f;
00027 }
00028 #else
00029 #define io_nonblock_mode(fd) ((void)(fd), 0)
00030 #endif
00031 
00032 #ifdef F_GETFL
00033 /*
00034  * call-seq:
00035  *   io.nonblock? -> boolean
00036  *
00037  * Returns +true+ if an IO object is in non-blocking mode.
00038  */
00039 static VALUE
00040 rb_io_nonblock_p(VALUE io)
00041 {
00042     rb_io_t *fptr;
00043     GetOpenFile(io, fptr);
00044     if (io_nonblock_mode(fptr->fd) & O_NONBLOCK)
00045         return Qtrue;
00046     return Qfalse;
00047 }
00048 #else
00049 #define rb_io_nonblock_p rb_f_notimplement
00050 #endif
00051 
00052 #ifdef F_SETFL
00053 static void
00054 io_nonblock_set(int fd, int f, int nb)
00055 {
00056     if (nb) {
00057         if ((f & O_NONBLOCK) != 0)
00058             return;
00059         f |= O_NONBLOCK;
00060     }
00061     else {
00062         if ((f & O_NONBLOCK) == 0)
00063             return;
00064         f &= ~O_NONBLOCK;
00065     }
00066     if (fcntl(fd, F_SETFL, f) == -1)
00067         rb_sys_fail(0);
00068 }
00069 
00070 /*
00071  * call-seq:
00072  *   io.nonblock = boolean -> boolean
00073  *
00074  * Enables non-blocking mode on a stream when set to
00075  * +true+, and blocking mode when set to +false+.
00076  */
00077 static VALUE
00078 rb_io_nonblock_set(VALUE io, VALUE nb)
00079 {
00080     rb_io_t *fptr;
00081     GetOpenFile(io, fptr);
00082     io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
00083     return io;
00084 }
00085 
00086 static VALUE
00087 io_nonblock_restore(VALUE arg)
00088 {
00089     int *restore = (int *)arg;
00090     if (fcntl(restore[0], F_SETFL, restore[1]) == -1)
00091         rb_sys_fail(0);
00092     return Qnil;
00093 }
00094 
00095 /*
00096  * call-seq:
00097  *   io.nonblock {|io| } -> io
00098  *   io.nonblock(boolean) {|io| } -> io
00099  *
00100  * Yields +self+ in non-blocking mode.
00101  *
00102  * When +false+ is given as an argument, +self+ is yielded in blocking mode.
00103  * The original mode is restored after the block is executed.
00104  */
00105 static VALUE
00106 rb_io_nonblock_block(int argc, VALUE *argv, VALUE io)
00107 {
00108     int nb = 1;
00109     rb_io_t *fptr;
00110     int f, restore[2];
00111 
00112     GetOpenFile(io, fptr);
00113     if (argc > 0) {
00114         VALUE v;
00115         rb_scan_args(argc, argv, "01", &v);
00116         nb = RTEST(v);
00117     }
00118     f = io_nonblock_mode(fptr->fd);
00119     restore[0] = fptr->fd;
00120     restore[1] = f;
00121     io_nonblock_set(fptr->fd, f, nb);
00122     return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore);
00123 }
00124 #else
00125 #define rb_io_nonblock_set rb_f_notimplement
00126 #define rb_io_nonblock_block rb_f_notimplement
00127 #endif
00128 
00129 void
00130 Init_nonblock(void)
00131 {
00132     rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0);
00133     rb_define_method(rb_cIO, "nonblock=", rb_io_nonblock_set, 1);
00134     rb_define_method(rb_cIO, "nonblock", rb_io_nonblock_block, -1);
00135 }
00136 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7