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() -> 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() -> 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);
}
|