From 74329237e6d49522ba0c169ca04039e041d02fff Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@factorcode.org>
Date: Fri, 18 Jan 2008 20:29:43 -0500
Subject: [PATCH] kqueue work in progress

---
 extra/io/unix/backend/kqueue/kqueue.factor | 67 +++++++++++++++-------
 extra/io/unix/unix.factor                  |  5 +-
 2 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/extra/io/unix/backend/kqueue/kqueue.factor b/extra/io/unix/backend/kqueue/kqueue.factor
index 35f2641e00..287b88c1c3 100644
--- a/extra/io/unix/backend/kqueue/kqueue.factor
+++ b/extra/io/unix/backend/kqueue/kqueue.factor
@@ -1,14 +1,16 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien.syntax kernel io.nonblocking io.unix.backend
-sequences assocs unix unix.kqueue math namespaces ;
+USING: alien.c-types kernel io.nonblocking io.unix.backend
+io.unix.sockets sequences assocs unix unix.kqueue math
+namespaces classes combinators ;
 IN: io.unix.backend.kqueue
 
 TUPLE: unix-kqueue-io ;
 
 ! Global variables
 SYMBOL: kqueue-fd
-SYMBOL: kqueue-changes
+SYMBOL: kqueue-added
+SYMBOL: kqueue-deleted
 SYMBOL: kqueue-events
 
 : max-events ( -- n )
@@ -17,26 +19,43 @@ SYMBOL: kqueue-events
     256 ; inline
 
 M: unix-kqueue-io init-unix-io ( -- )
-    V{ } clone kqueue-changes set-global
+    H{ } clone kqueue-added set-global
+    H{ } clone kqueue-deleted set-global
     max-events "kevent" <c-array> kqueue-events set-global
-    kqueue kqueue-fd dup io-error set-global ;
+    kqueue dup io-error kqueue-fd set-global ;
 
-: add-change ( event -- ) kqueue-changes get-global push ;
+M: unix-kqueue-io register-io-task ( task -- )
+    dup io-task-fd kqueue-added get-global key? [ drop ] [
+        dup io-task-fd kqueue-deleted get-global key? [
+            io-task-fd kqueue-deleted get-global delete-at
+        ] [
+            dup io-task-fd kqueue-added get-global set-at
+        ] if
+    ] if ;
+
+M: unix-kqueue-io unregister-io-task ( task -- )
+    dup io-task-fd kqueue-deleted get-global key? [ drop ] [
+        dup io-task-fd kqueue-added get-global key? [
+            io-task-fd kqueue-added get-global delete-at
+        ] [
+            dup io-task-fd kqueue-deleted get-global set-at
+        ] if
+    ] if ;
 
 : io-task-filter ( task -- n )
     class {
-        { read-task    EVFILT_READ  }
-        { accept-task  EVFILT_READ  }
-        { receive-task EVFILT_READ  }
-        { write-task   EVFILT_WRITE }
-        { connect-task EVFILT_WRITE }
-        { send-task    EVFILT_WRITE }
+        { read-task    [ EVFILT_READ  ] }
+        { accept-task  [ EVFILT_READ  ] }
+        { receive-task [ EVFILT_READ  ] }
+        { write-task   [ EVFILT_WRITE ] }
+        { connect-task [ EVFILT_WRITE ] }
+        { send-task    [ EVFILT_WRITE ] }
     } case ;
 
 : make-kevent ( task -- event )
     "kevent" <c-object>
     over io-task-fd over set-kevent-ident
-    over io-task-filter over set-kevent-filter ;
+    swap io-task-filter over set-kevent-filter ;
 
 : make-add-kevent ( task -- event )
     make-kevent
@@ -46,15 +65,19 @@ M: unix-kqueue-io init-unix-io ( -- )
     make-kevent
     EV_DELETE over set-kevent-flags ;
 
-M: unix-select-io register-io-task ( task -- )
-    make-add-kevent add-change ;
+: kqueue-additions ( -- kevents )
+    kqueue-added get-global
+    dup clear-assoc values
+    [ make-add-kevent ] map ;
 
-M: unix-select-io unregister-io-task ( task -- )
-    make-delete-kevent add-change ;
+: kqueue-deletions ( -- kevents )
+    kqueue-deleted get-global
+    dup clear-assoc values
+    [ make-delete-kevent ] map ;
 
 : kqueue-changelist ( -- byte-array n )
-    kqueue-changes get-global
-    dup concat f like over length rot delete-all ;
+    kqueue-additions kqueue-deletions append
+    dup concat f like swap length ;
 
 : kqueue-eventlist ( -- byte-array n )
     kqueue-events get-global max-events ;
@@ -67,15 +90,15 @@ M: unix-select-io unregister-io-task ( task -- )
     r> kevent dup multiplexer-error ;
 
 : kevent-task ( kevent -- task )
-    dup kevent-filter {
+    dup kevent-ident swap kevent-filter {
         { [ dup EVFILT_READ = ] [ read-tasks ] }
         { [ dup EVFILT_WRITE = ] [ write-tasks ] }
-    } cond get at ;
+    } cond nip get at ;
 
 : handle-kevents ( n eventlist -- )
     [ kevent-nth kevent-task handle-fd ] curry each ;
 
-M: unix-select-io unix-io-multiplex ( ms -- )
+M: unix-kqueue-io unix-io-multiplex ( ms -- )
     make-timespec
     do-kevent
     kqueue-events get-global handle-kevents ;
diff --git a/extra/io/unix/unix.factor b/extra/io/unix/unix.factor
index 1c86224433..3800008864 100755
--- a/extra/io/unix/unix.factor
+++ b/extra/io/unix/unix.factor
@@ -3,8 +3,9 @@ io.unix.launcher io.unix.mmap io.backend combinators namespaces
 system vocabs.loader ;
 
 {
-    { [ macosx? ] [ "io.unix.backend.kqueue" ] }
-    { [ bsd? ] [ "io.unix.backend.kqueue" ] }
+    ! kqueue is a work in progress
+    ! { [ macosx? ] [ "io.unix.backend.kqueue" ] }
+    ! { [ bsd? ] [ "io.unix.backend.kqueue" ] }
     { [ unix? ] [ "io.unix.backend.select" ] }
 } cond require