class SleepyPenguin::EventFD
Applications may use EventFD
instead of a pipe in cases where a pipe is only used to signal events. The kernel overhead for an EventFD
descriptor is much lower than that of a pipe.
As of Linux 2.6.30, an EventFD
may also be used as a semaphore.
Constants
- MAX
the maximum value that may be stored in an
EventFD
, currently 0xfffffffffffffffe
Public Class Methods
Creates an EventFD
object. initial_value
is a non-negative Integer to start the internal counter at.
Starting with Linux 2.6.27, flags
may be a mask that consists of any 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
Since Linux 2.6.30, flags
may also include:
-
:SEMAPHORE - provides semaphore-like semantics (see
EventFD#value
)
static VALUE s_new(int argc, VALUE *argv, VALUE klass) { VALUE _initval, _flags, rv; unsigned initval; int flags; int fd; rb_scan_args(argc, argv, "11", &_initval, &_flags); initval = NUM2UINT(_initval); flags = rb_sp_get_flags(klass, _flags, RB_SP_CLOEXEC(EFD_CLOEXEC)); fd = eventfd(initval, flags); if (fd < 0) { if (rb_sp_gc_for_fd(errno)) fd = eventfd(initval, flags); if (fd < 0) rb_sys_fail("eventfd"); } rv = INT2FIX(fd); return rb_call_super(1, &rv); }
Public Instance Methods
Increments the internal counter by integer_value
which is an unsigned Integer value.
If nonblock
is specified and true, this will return nil
if the internal counter will overflow the value of EventFD::MAX. Otherwise it will block until the counter may be incremented without overflowing.
static VALUE incr(int argc, VALUE *argv, VALUE self) { struct efd_args x; ssize_t w; VALUE value, nonblock; rb_scan_args(argc, argv, "11", &value, &nonblock); x.fd = rb_sp_fileno(self); if (RTEST(nonblock)) rb_sp_set_nonblock(x.fd); x.val = (uint64_t)NUM2ULL(value); retry: w = (ssize_t)rb_sp_fd_region(efd_write, &x, x.fd); if (w < 0) { if (errno == EAGAIN && RTEST(nonblock)) return Qfalse; if (rb_sp_wait(rb_io_wait_writable, self, &x.fd)) goto retry; rb_sys_fail("write(eventfd)"); } return Qtrue; }
If not created as a semaphore, returns the current value and resets the counter to zero.
If created as a semaphore, this decrements the counter value by one and returns 1
.
If the counter is zero at the time of the call, this will block until the counter becomes non-zero unless nonblock
is true
, in which case it returns nil
.
static VALUE getvalue(int argc, VALUE *argv, VALUE self) { struct efd_args x; ssize_t w; VALUE nonblock; rb_scan_args(argc, argv, "01", &nonblock); x.fd = rb_sp_fileno(self); if (RTEST(nonblock)) rb_sp_set_nonblock(x.fd); retry: w = (ssize_t)rb_sp_fd_region(efd_read, &x, x.fd); if (w < 0) { if (errno == EAGAIN && RTEST(nonblock)) return Qnil; if (rb_sp_wait(rb_io_wait_readable, self, &x.fd)) goto retry; rb_sys_fail("read(eventfd)"); } return ULL2NUM(x.val); }