about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-01-13 14:25:27 -0800
committerEric Wong <normalperson@yhbt.net>2011-01-13 14:25:27 -0800
commita29b597e57cfcdf6a25cb4e8c12094e059833878 (patch)
treebeb02bd6e4f857e10da6bbce599babd8a2c07627
parent9c44f01af3538fa51eeecd4944cca0ae1bc885b1 (diff)
downloadsleepy_penguin-a29b597e57cfcdf6a25cb4e8c12094e059833878.tar.gz
No need to burden applications.
-rw-r--r--ext/sleepy_penguin/epoll.c26
-rw-r--r--test/test_epoll.rb8
2 files changed, 34 insertions, 0 deletions
diff --git a/ext/sleepy_penguin/epoll.c b/ext/sleepy_penguin/epoll.c
index 06788ec..d06ece1 100644
--- a/ext/sleepy_penguin/epoll.c
+++ b/ext/sleepy_penguin/epoll.c
@@ -206,6 +206,8 @@ static VALUE ctl(VALUE self, VALUE io, VALUE flags, int op)
 }
 
 /*
+ * used to avoid exceptions when your app is too lazy to check
+ * what state a descriptor is in
  */
 static VALUE set(VALUE self, VALUE io, VALUE flags)
 {
@@ -232,6 +234,29 @@ static VALUE set(VALUE self, VALUE io, VALUE flags)
         return INT2NUM(rv);
 }
 
+/*
+ * Deletes an +io+ from an epoll set, but returns nil
+ * on ENOENT instead of raising an error.  This is useful
+ * for apps that do not care to track the status of an
+ * epoll object itself.
+ */
+static VALUE delete(VALUE self, VALUE io)
+{
+        struct rb_epoll *ep = ep_get(self);
+        int fd = my_fileno(io);
+        int rv;
+
+        ep_check(ep);
+        rv = epoll_ctl(ep->fd, EPOLL_CTL_DEL, fd, NULL);
+        if (rv == -1) {
+                if (errno != ENOENT)
+                        rb_sys_fail("epoll_ctl - del");
+                errno = 0;
+                return Qnil;
+        }
+        return INT2NUM(rv);
+}
+
 static VALUE epwait_result(struct rb_epoll *ep, int n)
 {
         int i;
@@ -548,6 +573,7 @@ void sleepy_penguin_init_epoll(void)
         rb_define_method(cEpoll, "add", add, 2);
         rb_define_method(cEpoll, "mod", mod, 2);
         rb_define_method(cEpoll, "del", del, 1);
+        rb_define_method(cEpoll, "delete", delete, 1);
         rb_define_method(cEpoll, "set", set, 2);
         rb_define_method(cEpoll, "wait", epwait, -1);
         rb_define_const(cEpoll, "CLOEXEC", INT2NUM(EPOLL_CLOEXEC));
diff --git a/test/test_epoll.rb b/test/test_epoll.rb
index 0386391..4b606ac 100644
--- a/test/test_epoll.rb
+++ b/test/test_epoll.rb
@@ -313,4 +313,12 @@ class TestEpoll < Test::Unit::TestCase
     io = Epoll.new.to_io
     assert((io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC) == Fcntl::FD_CLOEXEC)
   end
+
+  def test_delete
+    assert_nil @ep.delete(@rd)
+    assert_nil @ep.delete(@wr)
+    assert_nothing_raised { @ep.add @rd, Epoll::IN }
+    assert_equal 0, @ep.delete(@rd)
+    assert_nil @ep.delete(@rd)
+  end
 end