class Kqueue
Public Class Methods
new()
click to toggle source
static VALUE rb_kqueue_initialize(VALUE self) { rb_io_t *fp; int fd; fd = kqueue(); if (fd == -1) rb_sys_fail("kqueue"); rb_update_max_fd(fd); MakeOpenFile(self, fp); fp->fd = fd; fp->mode = FMODE_READABLE|FMODE_BINMODE; rb_io_ascii8bit_binmode(self); IVAR_SET(self, rb_hash_new()); return self; }
Public Instance Methods
kevent(p1, p2, p3 = v3)
click to toggle source
static VALUE rb_kqueue_kevent(int argc, VALUE *argv, VALUE self) { VALUE ch_list, max_events, timeout, ev, ready_evlist; struct kqueue_kevent_args args; struct timespec ts; struct timespec *pts = NULL; struct timeval tv; int i; int ev_len = 0, ch_len = 0; int ready; struct kevent *chl = NULL, *evl = NULL; rb_io_t *fptr, *fptr_io; fptr = RFILE(self)->fptr; rb_io_check_initialized(fptr); rb_scan_args(argc, argv, "21", &ch_list, &max_events, &timeout); if (!NIL_P(max_events)) { ev_len = FIX2INT(max_events); } if (!NIL_P(timeout)) { tv = rb_time_timeval(timeout); ts.tv_sec = (time_t)tv.tv_sec; ts.tv_nsec = (long)tv.tv_usec * 1000; pts = &ts; } if (!NIL_P(ch_list)) { Check_Type(ch_list, T_ARRAY); ch_len = RARRAY_LEN(ch_list); chl = alloca(sizeof(struct kevent) * ch_len); for (i = 0; i < ch_len; i++) { ev = RARRAY_AREF(ch_list, i); if (!rb_obj_is_kind_of(ev, cKqueue_Event)) { rb_raise(rb_eTypeError, "must be set Array of Event object"); } chl[i].ident = FIX2INT(RSTRUCT_GET(ev, IDENT)); chl[i].filter = FIX2INT(RSTRUCT_GET(ev, FILTER)); chl[i].flags = FIX2UINT(RSTRUCT_GET(ev, FLAGS)); chl[i].fflags = FIX2UINT(RSTRUCT_GET(ev, FFLAGS)); chl[i].data = NUM2LONG(RSTRUCT_GET(ev, DATA)); { VALUE fileno = RSTRUCT_GET(ev, IDENT); VALUE filter = RSTRUCT_GET(ev, FILTER); VALUE udata = RSTRUCT_GET(ev, UDATA); VALUE ivar = IVAR_GET(self); VALUE h = rb_hash_aref(ivar, fileno); if ((chl[i].flags & EV_DELETE) == EV_DELETE) { if (chl[i].flags & ~EV_DELETE) { rb_raise(rb_eArgError, "EV_DELETE cannot set with other"); } if (NIL_P(h)) { rb_raise(rb_eArgError, "delete udata not found"); } rb_hash_delete(h, filter); if (RHASH_EMPTY_P(h)) { rb_hash_delete(ivar, fileno); } udata = (VALUE)0; } else { if (NIL_P(h)) { h = rb_hash_aset(ivar, fileno, rb_hash_new()); } rb_hash_aset(h, filter, udata); } IVAR_SET(self, ivar); chl[i].udata = (void*)udata; } } } if (0 < ev_len) { evl = alloca(sizeof(struct kevent) * ev_len); } else if (ev_len < 0) { rb_raise(rb_eArgError, "negative size"); } args.fd = fptr->fd; args.chl = chl; args.ch_len = ch_len; args.evl = evl; args.ev_len = ev_len; args.ts = pts; RETRY: ready = (int)(long)rb_thread_call_without_gvl(rb_kqueue_kevent_func, &args, RUBY_UBF_IO, 0); if (ready == -1) { if (errno == EINTR) goto RETRY; else rb_sys_fail("kevent"); } ready_evlist = rb_ary_new_capa(ready); for (i = 0; i < ready; i++) { ev = rb_obj_alloc(cKqueue_Event); RSTRUCT_SET(ev, IDENT, INT2FIX(evl[i].ident)); RSTRUCT_SET(ev, FILTER, INT2FIX(evl[i].filter)); RSTRUCT_SET(ev, FLAGS, INT2FIX(evl[i].flags)); RSTRUCT_SET(ev, FFLAGS, INT2FIX(evl[i].fflags)); RSTRUCT_SET(ev, FLAGS, INT2FIX(evl[i].flags)); RSTRUCT_SET(ev, DATA, INT2FIX(evl[i].data)); RSTRUCT_SET(ev, UDATA, (VALUE)evl[i].udata); rb_ary_store(ready_evlist, i, ev); } return ready_evlist; }