diff options
Diffstat (limited to 'ext/sleepy_penguin/inotify.c')
-rw-r--r-- | ext/sleepy_penguin/inotify.c | 82 |
1 files changed, 49 insertions, 33 deletions
diff --git a/ext/sleepy_penguin/inotify.c b/ext/sleepy_penguin/inotify.c index b5cd67b..56fcff2 100644 --- a/ext/sleepy_penguin/inotify.c +++ b/ext/sleepy_penguin/inotify.c @@ -134,8 +134,11 @@ static VALUE event_new(struct inotify_event *e) } struct inread_args { + VALUE self; int fd; + int nonblock_p; size_t size; + VALUE tmp; void *buf; }; @@ -158,6 +161,7 @@ static void resize_internal_buffer(struct inread_args *args) if (newlen > 0) { args->size = (size_t)newlen; + rb_sp_puttlsbuf((VALUE)args->buf); args->buf = rb_sp_gettlsbuf(&args->size); } @@ -169,56 +173,35 @@ static void resize_internal_buffer(struct inread_args *args) newlen); } -/* - * call-seq: - * ino.take([nonblock]) -> Inotify::Event or nil - * - * Returns the next Inotify::Event processed. May return +nil+ if +nonblock+ - * is +true+. - */ -static VALUE take(int argc, VALUE *argv, VALUE self) +static VALUE do_take(VALUE p) { - struct inread_args args; - VALUE tmp = rb_ivar_get(self, id_inotify_tmp); - struct inotify_event *e, *end; - ssize_t r; + struct inread_args *args = (struct inread_args *)p; VALUE rv = Qnil; - VALUE nonblock; - - if (RARRAY_LEN(tmp) > 0) - return rb_ary_shift(tmp); - - rb_scan_args(argc, argv, "01", &nonblock); - - args.fd = rb_sp_fileno(self); - args.size = 128; - args.buf = rb_sp_gettlsbuf(&args.size); + struct inotify_event *e, *end; - if (RTEST(nonblock)) - rb_sp_set_nonblock(args.fd); - else - blocking_io_prepare(args.fd); + args->buf = rb_sp_gettlsbuf(&args->size); do { - r = (ssize_t)rb_sp_fd_region(inread, &args, args.fd); + ssize_t r = (ssize_t)rb_sp_fd_region(inread, args, args->fd); if (r == 0 /* Linux < 2.6.21 */ || (r < 0 && errno == EINVAL) /* Linux >= 2.6.21 */ ) { - resize_internal_buffer(&args); + resize_internal_buffer(args); } else if (r < 0) { - if (errno == EAGAIN && RTEST(nonblock)) + if (errno == EAGAIN && args->nonblock_p) return Qnil; - if (!rb_sp_wait(rb_io_wait_readable, self, &args.fd)) + if (!rb_sp_wait(rb_io_wait_readable, args->self, + &args->fd)) rb_sys_fail("read(inotify)"); } else { /* buffer in userspace to minimize read() calls */ - end = (struct inotify_event *)((char *)args.buf + r); - for (e = args.buf; e < end; ) { + end = (struct inotify_event *)((char *)args->buf + r); + for (e = args->buf; e < end; ) { VALUE event = event_new(e); if (NIL_P(rv)) rv = event; else - rb_ary_push(tmp, event); + rb_ary_push(args->tmp, event); e = (struct inotify_event *) ((char *)e + event_len(e)); } @@ -230,6 +213,39 @@ static VALUE take(int argc, VALUE *argv, VALUE self) /* * call-seq: + * ino.take([nonblock]) -> Inotify::Event or nil + * + * Returns the next Inotify::Event processed. May return +nil+ if +nonblock+ + * is +true+. + */ +static VALUE take(int argc, VALUE *argv, VALUE self) +{ + struct inread_args args; + VALUE nonblock; + + args.tmp = rb_ivar_get(self, id_inotify_tmp); + if (RARRAY_LEN(args.tmp) > 0) + return rb_ary_shift(args.tmp); + + rb_scan_args(argc, argv, "01", &nonblock); + + args.self = self; + args.fd = rb_sp_fileno(self); + args.size = 128; + args.nonblock_p = RTEST(nonblock); + + if (args.nonblock_p) + rb_sp_set_nonblock(args.fd); + else + blocking_io_prepare(args.fd); + + args.buf = 0; + return rb_ensure(do_take, (VALUE)&args, + rb_sp_puttlsbuf, (VALUE)args.buf); +} + +/* + * call-seq: * inotify_event.events => [ :MOVED_TO, ... ] * * Returns an array of symbolic event names based on the contents of |