<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -2,7 +2,6 @@ History.txt
 Manifest.txt
 README.txt
 Rakefile
-bin/ruby-kqueue
 lib/ruby-kqueue.rb
 lib/ruby-kqueue/event.rb
 lib/ruby-kqueue/vnode_event.rb</diff>
      <filename>Manifest.txt</filename>
    </modified>
    <modified>
      <diff>@@ -55,22 +55,30 @@ module RubyKQueue
         VALUE c_handle_events() {
           int nevents, i, num_to_fetch;
           struct kevent *events;
+          struct timespec timeout;
           fd_set read_set;
       
           FD_ZERO(&amp;read_set);
           FD_SET(kq, &amp;read_set);
-      
-          // Don't actually run this method until we've got an event
-          rb_thread_select(kq + 1, &amp;read_set, NULL, NULL, NULL);  
-      
+          
           events = (struct kevent*)malloc(MAX_EVENTS * sizeof(struct kevent));
-      
+          bzero(&amp;timeout, sizeof(struct timespec));
+          
           if (NULL == events) {
             rb_raise(rb_eStandardError, strerror(errno));
           }
       
-          nevents = kevent(kq, NULL, 0, events, MAX_EVENTS, NULL);
+          // Don't actually run this method until we've got an event
+          if (rb_thread_select(kq + 1, &amp;read_set, NULL, NULL, NULL) &lt;= 0) {
+            free(events);
+            rb_raise(rb_eStandardError, strerror(errno));
+          }
       
+          // In testing kevent has been blocking, even though select continues
+          // so set a tiny timeout just in case. It _should_ execute immediately
+          timeout.tv_nsec = 10;
+          nevents = kevent(kq, NULL, 0, events, MAX_EVENTS, &amp;timeout);
+          
           if (-1 == nevents) {
             free(events);
             rb_raise(rb_eStandardError, strerror(errno));
@@ -81,7 +89,7 @@ module RubyKQueue
           }
       
           free(events);
-      
+          
           return INT2FIX(nevents);
         }
       END
@@ -91,9 +99,13 @@ module RubyKQueue
     
     # TODO: Allow a lower level interface for direct manipulation
     #       of registration flags (EV_ONESHOT and the like)
-    def self.register(ident, filter_class, *flags, &amp;block)
-      ident = filter_class.normalize_ident(ident)
-      filter = filter_class::FILTER
+    def self.register(ident, filter_or_filter_class, *flags, &amp;block)
+      if filter_or_filter_class.is_a? Class
+        ident = filter_or_filter_class.normalize_ident(ident)
+        filter = filter_or_filter_class::FILTER
+      else
+        filter = filter_or_filter_class
+      end
       
       @@registry[filter] ||= {}
       @@registry[filter][ident] ||= {}
@@ -107,12 +119,34 @@ module RubyKQueue
       c_register(ident, EV_ADD | EV_ENABLE, filter, mask)
     end
     
+    def self.deregister(ident, filter_or_filter_class, *flags)
+      # puts &quot;Calling deregister&quot;
+      # puts &quot;Registry like: #{@@registry.inspect}&quot;
+      if filter_or_filter_class.is_a? Class
+        ident = filter_or_filter_class.normalize_ident(ident)
+        filter = filter_or_filter_class::FILTER
+      else
+        filter = filter_or_filter_class
+      end
+      
+      flags.each do |flag|
+        @@registry[filter][ident].delete(flag) rescue nil
+      end
+      
+      # puts &quot;Now registry like: #{@@registry.inspect}&quot;
+      
+      mask = flags.inject {|msk, flg| msk | flg }
+      
+      # puts &quot;Calling c_register&quot;
+      c_register(ident, EV_DELETE, filter, mask)
+    end
+    
     def self.trigger(id, filter, flag)
       Event.new(id, filter, flag).trigger
     end
     
     def self.handle
-      c_handle_events
+      @@handler_thread ||= Thread.new { loop { c_handle_events } }
     end
     
     def self.registry
@@ -158,6 +192,14 @@ module RubyKQueue
         # TODO: ignore or raise?
       end
     end
-            
+    
+    def register
+      self.class.register(self.id, self.filter, self.flag)
+    end
+    
+    def deregister
+      self.class.deregister(self.id, self.filter, self.flag)
+    end
+    
   end
 end
\ No newline at end of file</diff>
      <filename>lib/ruby-kqueue/event.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,22 +22,31 @@ module RubyKQueue
         42
       end
       
-      Event.new(@dir, VNodeEvent, VNodeEvent::WRITE).trigger.should == 42
-    
-      # TODO: Deregister
+      ev = Event.new(@dir, VNodeEvent, VNodeEvent::WRITE)
+      
+      ev.trigger.should == 42
+      
+      ev.deregister
+      
+      ev.trigger.should == nil
     end
     
-    it &quot;should be triggered by an event&quot; do      
+    it &quot;should be triggered by an event if registered&quot; do
       t = Thread.new { Event.handle }
       Event.register(@dir, VNodeEvent, VNodeEvent::WRITE) do
         $ret = 42
       end
       
       File.open(&quot;#{@dir}/writing&quot;, 'w+') {|f|}
+      sleep 0.00001
+      $ret.should == 42
       
-      sleep 0.001
+      Event.deregister(@dir, VNodeEvent, VNodeEvent::WRITE)
+      $ret = nil
       
-      $ret.should == 42
+      File.open(&quot;#{@dir}/writing_again&quot;, 'w+') {|f|}
+      sleep 0.00001
+      $ret.should == nil
     end
   end
   </diff>
      <filename>spec/event_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>bin/ruby-kqueue</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>b83fa685a421d74a509ca55543a81f2cbd27eac0</id>
    </parent>
  </parents>
  <author>
    <name>Kevin Clark</name>
    <email>kevin.clark@gmail.com</email>
  </author>
  <url>http://github.com/kevinclark/ruby-kqueue/commit/ee1e2e5306e2d6e1645a1ca57440edd9addee67a</url>
  <id>ee1e2e5306e2d6e1645a1ca57440edd9addee67a</id>
  <committed-date>2008-04-02T18:59:47-07:00</committed-date>
  <authored-date>2008-04-02T18:59:47-07:00</authored-date>
  <message>[NEW] Deregistration of events
[FIX] Don't block on kevent call
[API] Change Event.register to take a filter or filter class</message>
  <tree>17eb9edaf8d04499fda0800ba10fd015d908b9fc</tree>
  <committer>
    <name>Kevin Clark</name>
    <email>kevin.clark@gmail.com</email>
  </committer>
</commit>
