]> gitweb.factorcode.org Git - factor.git/blob - basis/io/backend/unix/multiplexers/kqueue/kqueue.factor
ab3308916db6787c6bf3bf24b2b15ec09493069c
[factor.git] / basis / io / backend / unix / multiplexers / kqueue / kqueue.factor
1 ! Copyright (C) 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types combinators destructors
4 io.backend.unix kernel math.bitwise sequences struct-arrays unix
5 unix.kqueue unix.time assocs io.backend.unix.multiplexers
6 classes.struct ;
7 IN: io.backend.unix.multiplexers.kqueue
8
9 TUPLE: kqueue-mx < mx events ;
10
11 ! We read up to 256 events at a time. This is an arbitrary
12 ! constant...
13 CONSTANT: max-events 256
14
15 : <kqueue-mx> ( -- mx )
16     kqueue-mx new-mx
17         kqueue dup io-error >>fd
18         max-events \ kevent <struct-array> >>events ;
19
20 M: kqueue-mx dispose* fd>> close-file ;
21
22 : make-kevent ( fd filter flags -- event )
23     \ kevent <struct>
24         swap >>flags
25         swap >>filter
26         swap >>ident ;
27
28 : register-kevent ( kevent mx -- )
29     fd>> swap 1 f 0 f kevent io-error ;
30
31 M: kqueue-mx add-input-callback ( thread fd mx -- )
32     [ call-next-method ] [
33         [ EVFILT_READ { EV_ADD EV_ONESHOT } flags make-kevent ] dip
34         register-kevent
35     ] 2bi ;
36
37 M: kqueue-mx add-output-callback ( thread fd mx -- )
38     [ call-next-method ] [
39         [ EVFILT_WRITE { EV_ADD EV_ONESHOT } flags make-kevent ] dip
40         register-kevent
41     ] 2bi ;
42
43 M: kqueue-mx remove-input-callbacks ( fd mx -- seq )
44     2dup reads>> key? [
45         [ call-next-method ] [
46             [ EVFILT_READ EV_DELETE make-kevent ] dip
47             register-kevent
48         ] 2bi
49     ] [ 2drop f ] if ;
50
51 M: kqueue-mx remove-output-callbacks ( fd mx -- seq )
52     2dup writes>> key? [
53         [
54             [ EVFILT_WRITE EV_DELETE make-kevent ] dip
55             register-kevent
56         ] [ call-next-method ] 2bi
57     ] [ 2drop f ] if ;
58
59 : wait-kevent ( mx timespec -- n )
60     [
61         [ fd>> f 0 ]
62         [ events>> dup length ] bi
63     ] dip kevent multiplexer-error ;
64
65 : handle-kevent ( mx kevent -- )
66     [ ident>> swap ] [ filter>> ] bi {
67         { EVFILT_READ [ input-available ] }
68         { EVFILT_WRITE [ output-available ] }
69     } case ;
70
71 : handle-kevents ( mx n -- )
72     [ dup events>> ] dip head-slice
73     [ handle-kevent ] with each ;
74
75 M: kqueue-mx wait-for-events ( us mx -- )
76     swap dup [ make-timespec ] when
77     dupd wait-kevent handle-kevents ;