factor/extra/io/nonblocking/nonblocking.factor

172 lines
4.3 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2008 Slava Pestov, Doug Coleman
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-02-09 22:34:42 -05:00
USING: math kernel io sequences io.buffers io.timeouts generic
byte-vectors system io.streams.duplex io.encodings
2008-02-09 22:34:42 -05:00
io.backend continuations debugger classes byte-arrays namespaces
2008-04-13 01:26:44 -04:00
splitting dlists assocs io.encodings.binary inspector accessors ;
2008-04-11 17:08:40 -04:00
IN: io.nonblocking
2007-09-20 18:09:08 -04:00
2007-11-07 14:01:45 -05:00
SYMBOL: default-buffer-size
64 1024 * default-buffer-size set-global
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
TUPLE: port handle buffer error timeout closed eof ;
2008-02-21 20:12:55 -05:00
2008-04-11 17:08:40 -04:00
M: port timeout timeout>> ;
2008-02-09 22:34:42 -05:00
2008-04-11 17:08:40 -04:00
M: port set-timeout (>>timeout) ;
2007-09-20 18:09:08 -04:00
GENERIC: init-handle ( handle -- )
2008-04-11 17:08:40 -04:00
2007-11-07 14:01:45 -05:00
GENERIC: close-handle ( handle -- )
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
: <port> ( handle class -- port )
new
2008-04-11 17:08:40 -04:00
swap dup init-handle >>handle ; inline
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
: <buffered-port> ( handle class -- port )
<port>
2008-04-11 17:08:40 -04:00
default-buffer-size get <buffer> >>buffer ; inline
TUPLE: input-port < port ;
2007-09-20 18:09:08 -04:00
2008-02-22 21:21:23 -05:00
: <reader> ( handle -- input-port )
2008-02-16 16:35:44 -05:00
input-port <buffered-port> ;
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
TUPLE: output-port < port ;
2008-02-22 21:21:23 -05:00
: <writer> ( handle -- output-port )
2008-02-16 16:35:44 -05:00
output-port <buffered-port> ;
2007-09-20 18:09:08 -04:00
: <reader&writer> ( read-handle write-handle -- input-port output-port )
2008-02-24 20:58:34 -05:00
swap <reader> [ swap <writer> ] [ ] [ dispose drop ] cleanup ;
2007-09-20 18:09:08 -04:00
: pending-error ( port -- )
[ f ] change-error drop [ throw ] when* ;
2007-09-20 18:09:08 -04:00
2008-04-13 01:26:44 -04:00
ERROR: port-closed-error port ;
M: port-closed-error summary
drop "Port has been closed" ;
2008-04-11 17:08:40 -04:00
: check-closed ( port -- port )
2008-04-13 01:26:44 -04:00
dup closed>> [ port-closed-error ] when ;
2008-04-11 17:08:40 -04:00
HOOK: cancel-io io-backend ( port -- )
M: object cancel-io drop ;
2008-02-09 22:34:42 -05:00
M: port timed-out cancel-io ;
2007-09-20 18:09:08 -04:00
GENERIC: (wait-to-read) ( port -- )
: wait-to-read ( count port -- )
tuck buffer>> buffer-length > [ (wait-to-read) ] [ drop ] if ;
2007-09-20 18:09:08 -04:00
: wait-to-read1 ( port -- )
1 swap wait-to-read ;
: unless-eof ( port quot -- value )
>r dup buffer>> buffer-empty? over eof>> and
[ f >>eof drop f ] r> if ; inline
2007-09-20 18:09:08 -04:00
M: input-port stream-read1
2008-04-11 17:08:40 -04:00
check-closed
dup wait-to-read1 [ buffer>> buffer-pop ] unless-eof ;
2007-09-20 18:09:08 -04:00
: read-step ( count port -- byte-array/f )
2007-09-20 18:09:08 -04:00
[ wait-to-read ] 2keep
[ dupd buffer>> buffer-read ] unless-eof nip ;
2007-09-20 18:09:08 -04:00
2008-03-08 03:51:26 -05:00
: read-loop ( count port accum -- )
2007-09-20 18:09:08 -04:00
pick over length - dup 0 > [
pick read-step dup [
over push-all read-loop
] [
2drop 2drop
] if
] [
2drop 2drop
] if ;
M: input-port stream-read
2008-04-11 17:08:40 -04:00
check-closed
2007-09-20 18:09:08 -04:00
>r 0 max >fixnum r>
2dup read-step dup [
pick over length > [
pick <byte-vector>
2007-09-20 18:09:08 -04:00
[ push-all ] keep
[ read-loop ] keep
B{ } like
] [ 2nip ] if
] [ 2nip ] if ;
2007-09-20 18:09:08 -04:00
M: input-port stream-read-partial ( max stream -- byte-array/f )
2008-04-11 17:08:40 -04:00
check-closed
2007-09-20 18:09:08 -04:00
>r 0 max >fixnum r> read-step ;
: can-write? ( len buffer -- ? )
2007-11-09 03:01:45 -05:00
[ buffer-fill + ] keep buffer-capacity <= ;
2007-09-20 18:09:08 -04:00
: wait-to-write ( len port -- )
tuck buffer>> can-write? [ drop ] [ stream-flush ] if ;
2007-09-20 18:09:08 -04:00
M: output-port stream-write1
2008-04-11 17:08:40 -04:00
check-closed
1 over wait-to-write
buffer>> byte>buffer ;
2007-09-20 18:09:08 -04:00
M: output-port stream-write
2008-04-11 17:08:40 -04:00
check-closed
over length over buffer>> buffer-size > [
[ buffer>> buffer-size <groups> ]
[ [ stream-write ] curry ] bi
each
2007-11-09 03:01:45 -05:00
] [
[ >r length r> wait-to-write ]
[ buffer>> >buffer ] 2bi
2007-11-09 03:01:45 -05:00
] if ;
2007-09-20 18:09:08 -04:00
2007-11-07 14:01:45 -05:00
GENERIC: port-flush ( port -- )
M: output-port stream-flush ( port -- )
2008-04-11 17:08:40 -04:00
check-closed
[ port-flush ] [ pending-error ] bi ;
2007-11-07 14:01:45 -05:00
2008-04-11 17:08:40 -04:00
GENERIC: close-port ( port -- )
M: output-port close-port
[ port-flush ] [ call-next-method ] bi ;
M: port close-port
dup cancel-io
dup handle>> close-handle
[ [ buffer-free ] when* f ] change-buffer drop ;
M: port dispose
2008-04-11 17:08:40 -04:00
dup closed>> [ drop ] [ t >>closed close-port ] if ;
2007-11-07 14:01:45 -05:00
2008-04-11 17:08:40 -04:00
TUPLE: server-port < port addr client client-addr encoding ;
2007-09-20 18:09:08 -04:00
: <server-port> ( handle addr encoding -- server )
rot server-port <port>
2008-04-11 17:08:40 -04:00
swap >>encoding
swap >>addr ;
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
: check-server-port ( port -- port )
dup server-port? [ "Not a server port" throw ] unless ; inline
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
TUPLE: datagram-port < port addr packet packet-addr ;
2007-09-20 18:09:08 -04:00
2008-01-21 15:33:43 -05:00
: <datagram-port> ( handle addr -- datagram )
2008-04-11 17:08:40 -04:00
swap datagram-port <port>
swap >>addr ;
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
: check-datagram-port ( port -- port )
check-closed
dup datagram-port? [ "Not a datagram port" throw ] unless ; inline
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
: check-datagram-send ( packet addrspec port -- packet addrspec port )
check-datagram-port
2dup addr>> [ class ] bi@ assert=
pick class byte-array assert= ;