Method: Kernel#select

Defined in:
io.c

- (Object) select(read_array)

[, error_array

[, timeout]]] ) =>  array  or  nil

See Kernel#select.



# File 'io.c'

/*
 *  call-seq:
 *     IO.select(read_array 
 *               [, write_array 
 *               [, error_array 
 *               [, timeout]]] ) =>  array  or  nil
 *  
 *  See <code>Kernel#select</code>.
 */

static VALUE
rb_f_select(argc, argv, obj)
    int argc;
    VALUE *argv;
    VALUE obj;
{
    VALUE read, write, except, timeout, res, list;
    fd_set rset, wset, eset, pset;
    fd_set *rp, *wp, *ep;
    struct timeval *tp, timerec;
    rb_io_t *fptr;
    long i;
    int max = 0, n;
    int interrupt_flag = 0;
    int pending = 0;

    rb_scan_args(argc, argv, "13", &read, &write, &except, &timeout);
    if (NIL_P(timeout)) {
    tp = 0;
    }
    else {
    timerec = rb_time_interval(timeout);
    tp = &timerec;
    }

    FD_ZERO(&pset);
    if (!NIL_P(read)) {
    Check_Type(read, T_ARRAY);
    rp = &rset;
    FD_ZERO(rp);
    for (i=0; i<RARRAY(read)->len; i++) {
        GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
        FD_SET(fileno(fptr->f), rp);
        if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */
        pending++;
        FD_SET(fileno(fptr->f), &pset);
        }
        if (max < fileno(fptr->f)) max = fileno(fptr->f);
    }
    if (pending) {     /* no blocking if there's buffered data */
        timerec.tv_sec = timerec.tv_usec = 0;
        tp = &timerec;
    }
    }
    else
    rp = 0;

    if (!NIL_P(write)) {
    Check_Type(write, T_ARRAY);
    wp = &wset;
    FD_ZERO(wp);
    for (i=0; i<RARRAY(write)->len; i++) {
        GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
        FD_SET(fileno(fptr->f), wp);
        if (max < fileno(fptr->f)) max = fileno(fptr->f);
        if (fptr->f2) {
        FD_SET(fileno(fptr->f2), wp);
        if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
        }
    }
    }
    else
    wp = 0;

    if (!NIL_P(except)) {
    Check_Type(except, T_ARRAY);
    ep = &eset;
    FD_ZERO(ep);
    for (i=0; i<RARRAY(except)->len; i++) {
        GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
        FD_SET(fileno(fptr->f), ep);
        if (max < fileno(fptr->f)) max = fileno(fptr->f);
        if (fptr->f2) {
        FD_SET(fileno(fptr->f2), ep);
        if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
        }
    }
    }
    else {
    ep = 0;
    }

    max++;

    n = rb_thread_select(max, rp, wp, ep, tp);
    if (n < 0) {
    rb_sys_fail(0);
    }
    if (!pending && n == 0) return Qnil; /* returns nil on timeout */

    res = rb_ary_new2(3);
    rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
    rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
    rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));

    if (interrupt_flag == 0) {
    if (rp) {
        list = RARRAY(res)->ptr[0];
        for (i=0; i< RARRAY(read)->len; i++) {
        GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
        if (FD_ISSET(fileno(fptr->f), rp)
            || FD_ISSET(fileno(fptr->f), &pset)) {
            rb_ary_push(list, rb_ary_entry(read, i));
        }
        }
    }

    if (wp) {
        list = RARRAY(res)->ptr[1];
        for (i=0; i< RARRAY(write)->len; i++) {
        GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
        if (FD_ISSET(fileno(fptr->f), wp)) {
            rb_ary_push(list, rb_ary_entry(write, i));
        }
        else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), wp)) {
            rb_ary_push(list, rb_ary_entry(write, i));
        }
        }
    }

    if (ep) {
        list = RARRAY(res)->ptr[2];
        for (i=0; i< RARRAY(except)->len; i++) {
        GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
        if (FD_ISSET(fileno(fptr->f), ep)) {
            rb_ary_push(list, rb_ary_entry(except, i));
        }
        else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), ep)) {
            rb_ary_push(list, rb_ary_entry(except, i));
        }
        }
    }
    }

    return res;         /* returns an empty array on interrupt */
}

Comments