Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
supplement / lib / supplement / itimer.c
Size: Mime:
/*
 *  supplement/itimer.c  --  Interval timer
 */


#include "itimer.h"

#include <sys/time.h>

static void  suppelement_sec_timeval( VALUE, struct timeval *t);
static VALUE suppelement_timeval_sec( struct timeval *);


/*
 *  call-seq:
 *     Process.setitimer( interval = nil, value = nil)   -> nil
 *
 *  Set alarm timer. If <code>value</code> is nonzero, it is the
 *  expiration time to the first alarm. If it is zero, the timer is disabled.
 *  If <code>value</code> is nonzero and <code>interval</code> is zero,
 *  the alarm is triggered once.
 *
 */

VALUE
rb_process_setitimer( int argc, VALUE *argv, VALUE obj)
{
    VALUE isec;
    VALUE vsec;
    struct itimerval it;

    rb_scan_args( argc, argv, "02", &isec, &vsec);

    suppelement_sec_timeval( isec, &it.it_interval);
    if (NIL_P(vsec) && !NIL_P(isec))
        it.it_value = it.it_interval;
    else
    suppelement_sec_timeval( vsec, &it.it_value);

    if (setitimer( ITIMER_REAL, &it, NULL) < 0)
        rb_raise( rb_eSystemCallError, "setitimer failed.");
    return Qnil;
}

void
suppelement_sec_timeval( VALUE secs, struct timeval *t)
{
    switch (TYPE(secs)) {
      case T_FIXNUM:
        t->tv_sec = FIX2LONG(secs), t->tv_usec = 0;
        if (t->tv_sec < 0)
            rb_raise( rb_eArgError, "time interval must be positive");
        break;

      case T_FLOAT:
        if (RFLOAT_VALUE(secs) < 0.0)
            rb_raise( rb_eArgError, "time interval must be positive");
        else {
            double f, d;

            d = modf( RFLOAT_VALUE(secs), &f);
            t->tv_sec = (time_t) f, t->tv_usec = (time_t) (d*1e6+0.5);
            if (f != t->tv_sec)
                rb_raise( rb_eRangeError, "time interval %f out of Time range",
                    RFLOAT_VALUE(secs));
        }
        break;

      case T_BIGNUM:
        t->tv_sec = NUM2LONG(secs), t->tv_usec = 0;
        if (t->tv_sec < 0)
            rb_raise(rb_eArgError, "time interval must be positive");
        break;

      case T_NIL:
        t->tv_sec = 0, t->tv_usec = 0;
        break;

      default:
        rb_raise( rb_eTypeError, "can't convert %s into time interval",
                 rb_obj_classname( secs));
        break;
    }
}


/*
 *  call-seq:
 *     Process.getitimer -> [interval, value]
 *
 *  Returns the interval and the remaining seconds to next alarm.
 */

VALUE
rb_process_getitimer( VALUE obj)
{
    struct itimerval it;
    VALUE r;

    if (getitimer( ITIMER_REAL, &it) < 0)
        rb_raise( rb_eSystemCallError, "getitimer failed.");

    r = rb_ary_new3( 2,
      suppelement_timeval_sec( &it.it_interval),
      suppelement_timeval_sec( &it.it_value));
    return r;
}

VALUE
suppelement_timeval_sec( struct timeval *t)
{
    VALUE r;
    if (t->tv_usec)
        r = rb_float_new( t->tv_sec + (1e-6 * t->tv_usec));
    else
        r = INT2NUM(t->tv_sec);
    return r;
}


void Init_itimer( void)
{
    rb_define_singleton_method( rb_mProcess, "setitimer", rb_process_setitimer, -1);
    rb_define_singleton_method( rb_mProcess, "getitimer", rb_process_getitimer, 0);
}