From 31dee76d5ef41ec5524c3e4dfb802db4a7a468ef Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 24 Dec 2010 18:11:04 -0800 Subject: remove rb_time_interval() and gettimeofday() dependency This function isn't exported in the standard Ruby headers, it returns an aggregate value and isn't available in Rubinius, either, so nuke it. While we're at it, use clock_gettime() instead of gettimeofday() to avoid unnecessary timeval usage since mq_send/mq_receive rely on higher-precision timespecs instead. --- ext/posix_mq/extconf.rb | 1 + ext/posix_mq/posix_mq.c | 65 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 9 deletions(-) (limited to 'ext/posix_mq') diff --git a/ext/posix_mq/extconf.rb b/ext/posix_mq/extconf.rb index b473c13..d34288b 100644 --- a/ext/posix_mq/extconf.rb +++ b/ext/posix_mq/extconf.rb @@ -8,6 +8,7 @@ have_header("pthread.h") have_func("rb_str_set_len") have_func("rb_struct_alloc_noinit") have_func('rb_thread_blocking_region') +have_library("m") have_library("rt") have_library("pthread") dir_config("posix_mq") diff --git a/ext/posix_mq/posix_mq.c b/ext/posix_mq/posix_mq.c index 73d139b..b634a91 100644 --- a/ext/posix_mq/posix_mq.c +++ b/ext/posix_mq/posix_mq.c @@ -10,6 +10,10 @@ #endif #include +#ifndef NUM2TIMET +# define NUM2TIMET NUM2INT +#endif + #ifndef RB_GC_GUARD # define RB_GC_GUARD(v) (*(volatile VALUE *)&(v)) #endif @@ -21,6 +25,8 @@ #include #include #include +#include +#include #if defined(__linux__) # define MQD_TO_FD(mqd) (int)(mqd) @@ -61,7 +67,7 @@ static int MQ_IO_CLOSE(struct posix_mq *mq) #endif static VALUE cPOSIX_MQ, cAttr; -static ID id_new, id_kill, id_fileno; +static ID id_new, id_kill, id_fileno, id_mul, id_divmod; static ID sym_r, sym_w, sym_rw; static const mqd_t MQD_INVALID = (mqd_t)-1; @@ -141,24 +147,63 @@ struct rw_args { struct timespec *timeout; }; -/* hope it's there..., TODO: a better version that works in rbx */ -struct timeval rb_time_interval(VALUE); +static void num2timespec(struct timespec *ts, VALUE t) +{ + switch (TYPE(t)) { + case T_FIXNUM: + case T_BIGNUM: + ts->tv_sec = NUM2TIMET(t); + ts->tv_nsec = 0; + break; + case T_FLOAT: { + double f, d; + double val = RFLOAT_VALUE(t); + + d = modf(val, &f); + if (d >= 0) { + ts->tv_nsec = (long)(d * 1e9 + 0.5); + } else { + ts->tv_nsec = (long)(-d * 1e9 + 0.5); + if (ts->tv_nsec > 0) { + ts->tv_nsec = 1000000000 - ts->tv_nsec; + f -= 1; + } + } + ts->tv_sec = (time_t)f; + if (f != ts->tv_sec) + rb_raise(rb_eRangeError, "%f out of range", val); + ts->tv_sec = (time_t)f; + } + break; + default: { + VALUE f; + VALUE ary = rb_funcall(t, id_divmod, 1, INT2FIX(1)); + + Check_Type(ary, T_ARRAY); + + ts->tv_sec = NUM2TIMET(rb_ary_entry(ary, 0)); + f = rb_ary_entry(ary, 1); + f = rb_funcall(f, id_mul, 1, INT2FIX(1000000000)); + ts->tv_nsec = NUM2LONG(f); + } + } +} static struct timespec *convert_timeout(struct timespec *dest, VALUE t) { - struct timeval tv, now; + struct timespec ts, now; if (NIL_P(t)) return NULL; - tv = rb_time_interval(t); /* aggregate return :( */ - gettimeofday(&now, NULL); - dest->tv_sec = now.tv_sec + tv.tv_sec; - dest->tv_nsec = (now.tv_usec + tv.tv_usec) * 1000; + num2timespec(&ts, t); + clock_gettime(CLOCK_REALTIME, &now); + dest->tv_sec = now.tv_sec + ts.tv_sec; + dest->tv_nsec = now.tv_nsec + ts.tv_nsec; if (dest->tv_nsec > 1000000000) { dest->tv_nsec -= 1000000000; - dest->tv_sec++; + ++dest->tv_sec; } return dest; @@ -961,6 +1006,8 @@ void Init_posix_mq_ext(void) id_new = rb_intern("new"); id_kill = rb_intern("kill"); id_fileno = rb_intern("fileno"); + id_mul = rb_intern("*"); + id_divmod = rb_intern("divmod"); sym_r = ID2SYM(rb_intern("r")); sym_w = ID2SYM(rb_intern("w")); sym_rw = ID2SYM(rb_intern("rw")); -- cgit v1.2.3-24-ge0c7