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