Class: SleepyPenguin::EventFD
- Inherits:
-
IO
- Object
- IO
- SleepyPenguin::EventFD
- Defined in:
- ext/sleepy_penguin/eventfd.c,
ext/sleepy_penguin/eventfd.c
Overview
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.
Constant Summary collapse
- MAX =
the maximum value that may be stored in an EventFD, currently 0xfffffffffffffffe
ULL2NUM(0xfffffffffffffffeULL)
Class Method Summary collapse
-
.new(*args) ⇒ Object
EventFD.new(initial_value [, flags]) -> EventFD IO object.
Instance Method Summary collapse
-
#incr(*args) ⇒ Object
efd.incr(integer_value[, nonblock ]) -> true or nil.
-
#value(*args) ⇒ Object
efd.value([nonblock]) -> Integer or nil.
Class Method Details
.new(*args) ⇒ Object
EventFD.new(initial_value [, flags]) -> EventFD IO object
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)
21 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/eventfd.c', line 21 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); } |
Instance Method Details
#incr(*args) ⇒ Object
efd.incr(integer_value[, nonblock ]) -> true or nil
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.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'ext/sleepy_penguin/eventfd.c', line 77 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; } |
#value(*args) ⇒ Object
efd.value([nonblock]) -> Integer or nil
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.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'ext/sleepy_penguin/eventfd.c', line 116 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); } |