1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/**********************************************************************
io/wait.c -
$Author$
created at: Tue Jul 14 21:53:18 2009
All the files in this distribution are covered under the Ruby's
license (see the file COPYING).
**********************************************************************/
#include "ruby.h"
#include "ruby/io.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#ifdef F_GETFL
static int
io_nonblock_mode(int fd)
{
int f = fcntl(fd, F_GETFL);
if (f == -1) rb_sys_fail(0);
return f;
}
#else
#define io_nonblock_mode(fd) ((void)(fd), 0)
#endif
#ifdef F_GETFL
/*
* call-seq:
* io.nonblock? -> boolean
*
* Returns +true+ if an IO object is in non-blocking mode.
*/
static VALUE
rb_io_nonblock_p(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (io_nonblock_mode(fptr->fd) & O_NONBLOCK)
return Qtrue;
return Qfalse;
}
#else
#define rb_io_nonblock_p rb_f_notimplement
#endif
#ifdef F_SETFL
static void
io_nonblock_set(int fd, int f, int nb)
{
if (nb) {
if ((f & O_NONBLOCK) != 0)
return;
f |= O_NONBLOCK;
}
else {
if ((f & O_NONBLOCK) == 0)
return;
f &= ~O_NONBLOCK;
}
if (fcntl(fd, F_SETFL, f) == -1)
rb_sys_fail(0);
}
/*
* call-seq:
* io.nonblock = boolean -> boolean
*
* Enables non-blocking mode on a stream when set to
* +true+, and blocking mode when set to +false+.
*/
static VALUE
rb_io_nonblock_set(VALUE io, VALUE nb)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
return io;
}
static VALUE
io_nonblock_restore(VALUE arg)
{
int *restore = (int *)arg;
if (fcntl(restore[0], F_SETFL, restore[1]) == -1)
rb_sys_fail(0);
return Qnil;
}
/*
* call-seq:
* io.nonblock {|io| } -> io
* io.nonblock(boolean) {|io| } -> io
*
* Yields +self+ in non-blocking mode.
*
* When +false+ is given as an argument, +self+ is yielded in blocking mode.
* The original mode is restored after the block is executed.
*/
static VALUE
rb_io_nonblock_block(int argc, VALUE *argv, VALUE io)
{
int nb = 1;
rb_io_t *fptr;
int f, restore[2];
GetOpenFile(io, fptr);
if (argc > 0) {
VALUE v;
rb_scan_args(argc, argv, "01", &v);
nb = RTEST(v);
}
f = io_nonblock_mode(fptr->fd);
restore[0] = fptr->fd;
restore[1] = f;
io_nonblock_set(fptr->fd, f, nb);
return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore);
}
#else
#define rb_io_nonblock_set rb_f_notimplement
#define rb_io_nonblock_block rb_f_notimplement
#endif
void
Init_nonblock(void)
{
rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0);
rb_define_method(rb_cIO, "nonblock=", rb_io_nonblock_set, 1);
rb_define_method(rb_cIO, "nonblock", rb_io_nonblock_block, -1);
}
|