Example #1
0
/*
 * call-seq:
 *   io.wait_writable          -> IO
 *   io.wait_writable(timeout) -> IO or nil
 *
 * Waits until IO writable is available or times out and returns self or
 * nil when EOF is reached.
 */
static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    int i;
    VALUE timeout;
    struct timeval timerec;
    struct timeval *tv;

    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);
    rb_scan_args(argc, argv, "01", &timeout);
    if (NIL_P(timeout)) {
	tv = NULL;
    }
    else {
	timerec = rb_time_interval(timeout);
	tv = &timerec;
    }

    i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_OUT, tv);
    if (i < 0)
	rb_sys_fail(0);
    rb_io_check_closed(fptr);
    if (i & RB_WAITFD_OUT)
	return io;
    return Qnil;
}
Example #2
0
File: wait.c Project: 7kaji/try
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
{
	struct timeval tv = rb_time_interval(timeout);
	int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;

	return rb_wait_for_single_fd(my_fileno(self), events, &tv);
}
Example #3
0
static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    int i;
    ioctl_arg n;
    VALUE timeout;
    struct timeval timerec;
    struct timeval *tv;

    GetOpenFile(io, fptr);
    rb_io_check_readable(fptr);
    rb_scan_args(argc, argv, "01", &timeout);
    if (NIL_P(timeout)) {
	tv = NULL;
    }
    else {
	timerec = rb_time_interval(timeout);
	tv = &timerec;
    }

    if (rb_io_read_pending(fptr)) return Qtrue;
    if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
    i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv);
    if (i < 0)
	rb_sys_fail(0);
    rb_io_check_closed(fptr);
    if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
    if (n > 0) return io;
    return Qnil;
}
Example #4
0
static VALUE
thread_runnable_sleep(VALUE thread, VALUE timeout)
{
    struct timeval timeval;

    if (NIL_P(timeout)) {
	rb_raise(rb_eArgError, "timeout must be non nil");
    }

    timeval = rb_time_interval(timeout);

    rb_thread_call_without_gvl(native_sleep_callback, &timeval, RUBY_UBF_IO, NULL);

    return thread;
}
Example #5
0
VALUE
rb_mutex_sleep(VALUE self, VALUE timeout)
{
    time_t beg, end;
    struct timeval t;

    if (!NIL_P(timeout)) {
        t = rb_time_interval(timeout);
    }
    rb_mutex_unlock(self);
    beg = time(0);
    if (NIL_P(timeout)) {
	rb_ensure(rb_mutex_sleep_forever, Qnil, rb_mutex_lock, self);
    }
    else {
	rb_ensure(rb_mutex_wait_for, (VALUE)&t, rb_mutex_lock, self);
    }
    end = time(0) - beg;
    return INT2FIX(end);
}
Example #6
0
static VALUE
mutex_sleep(VALUE self, SEL sel, int argc, VALUE *argv)
{
    VALUE timeout;
    rb_scan_args(argc, argv, "01", &timeout);

    rb_mutex_unlock(self, 0);
    
    time_t beg, end;
    beg = time(0);

    if (timeout == Qnil) {
	rb_thread_sleep_forever();	
    }
    else {
	struct timeval t = rb_time_interval(timeout);
	rb_thread_wait_for(t);
    }

    end = time(0) - beg;
    return INT2FIX(end);        
}
Example #7
0
static VALUE
thread_join_m(VALUE self, SEL sel, int argc, VALUE *argv)
{
    VALUE timeout;

    rb_scan_args(argc, argv, "01", &timeout);

    rb_vm_thread_t *t = GetThreadPtr(self);
    if (t->status != THREAD_DEAD) {
	if (timeout == Qnil) {
	    // No timeout given: block until the thread finishes.
	    pthread_assert(pthread_join(t->thread, NULL));
	}
	else {
	    // Timeout given: sleep then check if the thread is dead.
	    // TODO do multiple sleeps instead of only one.
	    struct timeval tv = rb_time_interval(timeout);
	    struct timespec ts;
	    ts.tv_sec = tv.tv_sec;
	    ts.tv_nsec = tv.tv_usec * 1000;
	    while (ts.tv_nsec >= 1000000000) {
		ts.tv_sec += 1;
		ts.tv_nsec -= 1000000000;
	    }
	    nanosleep(&ts, NULL);
	    if (t->status != THREAD_DEAD) {
		return Qnil;
	    }
	}
    }

    // If the thread was terminated because of an exception, we need to
    // propagate it.
    if (t->exception != Qnil) {
	rb_exc_raise(t->exception);
    }

    return self;
}
Example #8
0
static VALUE
thread_join_m(VALUE self, SEL sel, int argc, VALUE *argv)
{
    VALUE timeout;

    rb_scan_args(argc, argv, "01", &timeout);

    rb_vm_thread_t *t = GetThreadPtr(self);
    if (t->status != THREAD_DEAD) {
	if (timeout == Qnil) {
	    // No timeout given: block until the thread finishes.
	    //pthread_assert(pthread_join(t->thread, NULL));
	    struct timespec ts;
	    ts.tv_sec = 0;
	    ts.tv_nsec = 10000000;
	    while (t->status != THREAD_DEAD) {
		nanosleep(&ts, NULL);
		pthread_yield_np();
		if (t->status == THREAD_KILLED && t->wait_for_mutex_lock) {
		    goto dead;
		}
	    }
	}
	else {
	    // Timeout given: sleep and check if the thread is dead.
	    struct timeval tv = rb_time_interval(timeout);
	    struct timespec ts;
	    ts.tv_sec = tv.tv_sec;
	    ts.tv_nsec = tv.tv_usec * 1000;
	    while (ts.tv_nsec >= 1000000000) {
		ts.tv_sec += 1;
		ts.tv_nsec -= 1000000000;
	    }

	    while (ts.tv_sec > 0 || ts.tv_nsec > 0) {
		struct timespec its;
again:
		if (ts.tv_nsec > 100000000) {
		    ts.tv_nsec -= 100000000;
		    its.tv_sec = 0;
		    its.tv_nsec = 100000000;
		}
		else if (ts.tv_sec > 0) {
		    ts.tv_sec -= 1;
		    ts.tv_nsec += 1000000000;
		    goto again;
		}
		else {
		    its = ts;
		    ts.tv_sec = ts.tv_nsec = 0;
		}
		nanosleep(&its, NULL);
		if (t->status == THREAD_DEAD) {
		    goto dead;
		}
		if (t->status == THREAD_KILLED && t->wait_for_mutex_lock) {
		    goto dead;
		}
	    }
	    return Qnil;
	}
    }

dead:
    // If the thread was terminated because of an exception, we need to
    // propagate it.
    if (t->exception != Qnil) {
	t->joined_on_exception = true;
	rb_exc_raise(t->exception);
    }
    return self;
}