1 ! Copyright (C) 2008 Slava Pestov.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types alien.data combinators
4 destructors io.backend.unix libc kernel math.bitwise sequences
5 specialized-arrays unix unix.kqueue unix.time assocs
6 io.backend.unix.multiplexers classes.struct literals ;
7 SPECIALIZED-ARRAY: kevent
8 IN: io.backend.unix.multiplexers.kqueue
10 TUPLE: kqueue-mx < mx events ;
12 ! We read up to 256 events at a time. This is an arbitrary
14 CONSTANT: max-events 256
16 : <kqueue-mx> ( -- mx )
18 kqueue dup io-error >>fd
19 max-events \ kevent <c-array> >>events ;
21 M: kqueue-mx dispose* fd>> close-file ;
23 : make-kevent ( fd filter flags -- event )
29 : register-kevent ( kevent mx -- )
30 fd>> swap 1 f 0 f kevent-func io-error ;
32 M: kqueue-mx add-input-callback
33 [ call-next-method ] [
34 [ EVFILT_READ flags{ EV_ADD EV_ONESHOT } make-kevent ] dip
38 M: kqueue-mx add-output-callback
39 [ call-next-method ] [
40 [ EVFILT_WRITE flags{ EV_ADD EV_ONESHOT } make-kevent ] dip
44 M: kqueue-mx remove-input-callbacks
46 [ call-next-method ] [
47 [ EVFILT_READ EV_DELETE make-kevent ] dip
52 M: kqueue-mx remove-output-callbacks
55 [ EVFILT_WRITE EV_DELETE make-kevent ] dip
57 ] [ call-next-method ] 2bi
60 : wait-kevent ( mx timespec -- n )
63 [ events>> dup length ] bi
64 ] dip kevent-func multiplexer-error ;
66 : handle-kevent ( mx kevent -- )
67 [ ident>> swap ] [ filter>> ] bi {
68 { EVFILT_READ [ input-available ] }
69 { EVFILT_WRITE [ output-available ] }
72 : handle-kevents ( mx n -- )
73 [ dup events>> ] dip head-slice
74 [ handle-kevent ] with each ;
76 M: kqueue-mx wait-for-events
77 swap dup [ make-timespec ] when
78 dupd wait-kevent handle-kevents ;