Class: SleepyPenguin::TimerFD

Inherits:
IO
  • Object
show all
Defined in:
ext/sleepy_penguin/timerfd.c,
ext/sleepy_penguin/timerfd.c

Overview

TimerFD exposes kernel timers as IO objects that may be monitored by IO.select or Epoll. IO#close disarms the timers and returns resources back to the kernel.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(*args) ⇒ Object

TimerFD.new([clockid[, flags]]) -> TimerFD IO object

Creates a new timer as an IO object.

If set clockid must be be one of the following:

  • :REALTIME - use the settable clock

  • :MONOTONIC - use the non-settable clock unaffected by manual changes

clockid defaults to :MONOTONIC if unspecified flags may be any or none of the following:

  • :CLOEXEC - set the close-on-exec flag on the new object

  • :NONBLOCK - set the non-blocking I/O flag on the new object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'ext/sleepy_penguin/timerfd.c', line 22

static VALUE s_new(int argc, VALUE *argv, VALUE klass)
{
	VALUE cid, fl, rv;
	int clockid, flags;
	int fd;

	rb_scan_args(argc, argv, "02", &cid, &fl);
	clockid = NIL_P(cid) ? CLOCK_MONOTONIC : rb_sp_get_flags(klass, cid, 0);
	flags = rb_sp_get_flags(klass, fl, RB_SP_CLOEXEC(TFD_CLOEXEC));

	fd = timerfd_create(clockid, flags);
	if (fd < 0) {
		if (rb_sp_gc_for_fd(errno))
			fd = timerfd_create(clockid, flags);
		if (fd < 0)
			rb_sys_fail("timerfd_create");
	}

	rv = INT2FIX(fd);
	return rb_call_super(1, &rv);
}

Instance Method Details

#expirations(*args) ⇒ Object

tfd.expirations() -> Integer

Returns the number of expirations that have occurred. This will block if no expirations have occurred at the time of the call. Returns nil if nonblock is passed and is true



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'ext/sleepy_penguin/timerfd.c', line 113

static VALUE expirations(int argc, VALUE *argv, VALUE self)
{
	ssize_t r;
	int fd = rb_sp_fileno(self);
	uint64_t buf = (uint64_t)fd;
	VALUE nonblock;

	rb_scan_args(argc, argv, "01", &nonblock);
	if (RTEST(nonblock))
		rb_sp_set_nonblock(fd);
retry:
	r = (ssize_t)rb_sp_fd_region(tfd_read, &buf, fd);
	if (r < 0) {
		if (errno == EAGAIN && RTEST(nonblock))
			return Qnil;
		if (rb_sp_wait(rb_io_wait_readable, self, &fd))
			goto retry;
		rb_sys_fail("read(timerfd)");
	}

	return ULL2NUM(buf);
}

#gettimeObject

tfd#gettime -> [ interval, value ]

Returns the current interval and value of the timer as an Array.



85
86
87
88
89
90
91
92
93
94
# File 'ext/sleepy_penguin/timerfd.c', line 85

static VALUE gettime(VALUE self)
{
	int fd = rb_sp_fileno(self);
	struct itimerspec curr;

	if (timerfd_gettime(fd, &curr) < 0)
		rb_sys_fail("timerfd_gettime");

	return itimerspec2ary(&curr);
}

#settime(fl, interval, value) ⇒ Object

tfd.settime(flags, interval, value) -> [ old_interval, old_value ]

Arms (starts) or disarms (stops) the timer referred by the TimerFD object and returns the old value of the timer.

flags is either zero (or nil) to start a relative timer or :ABSTIME to start an absolute timer. If the interval is zero, the timer fires only once, otherwise the timer is fired every interval seconds. value is the time of the initial expiration in seconds.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'ext/sleepy_penguin/timerfd.c', line 64

static VALUE settime(VALUE self, VALUE fl, VALUE interval, VALUE value)
{
	int fd = rb_sp_fileno(self);
	int flags = rb_sp_get_flags(self, fl, 0);
	struct itimerspec old, new;

	value2timespec(&new.it_interval, interval);
	value2timespec(&new.it_value, value);

	if (timerfd_settime(fd, flags, &new, &old) < 0)
		rb_sys_fail("timerfd_settime");

	return itimerspec2ary(&old);
}