From e9d80dcb637c01dd4614d63215affa854dc44edf Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 11 Dec 2008 22:48:19 -0600 Subject: [PATCH] Move Unix I/O multiplexers to io.unix.multiplexers, new run loop-based multiplexer integrates a kqueue with a CFRunLoop on Mac OS X --- basis/core-foundation/core-foundation.factor | 15 +++- .../core-foundation/fsevents/fsevents.factor | 8 +- .../core-foundation/run-loop/run-loop.factor | 6 ++ .../run-loop/thread/summary.txt | 1 - .../run-loop/thread/thread.factor | 16 ---- basis/io/unix/backend/backend.factor | 34 +-------- basis/io/unix/bsd/bsd.factor | 3 +- basis/io/unix/linux/linux.factor | 4 +- basis/io/unix/linux/monitors/monitors.factor | 8 +- basis/io/unix/macosx/macosx.factor | 7 +- .../unix/multiplexers/epoll}/authors.txt | 0 basis/io/unix/multiplexers/epoll/epoll.factor | 66 ++++++++++++++++ .../unix/multiplexers/epoll}/tags.txt | 0 basis/io/unix/multiplexers/kqueue/authors.txt | 1 + .../io/unix/multiplexers/kqueue/kqueue.factor | 76 +++++++++++++++++++ basis/io/unix/multiplexers/kqueue/tags.txt | 1 + .../io/unix/multiplexers/multiplexers.factor | 35 +++++++++ .../multiplexers/run-loop/run-loop.factor | 57 ++++++++++++++ basis/io/unix/multiplexers/run-loop/tags.txt | 1 + basis/io/unix/multiplexers/select/authors.txt | 1 + .../io/unix/multiplexers/select/select.factor | 56 ++++++++++++++ basis/io/unix/multiplexers/select/tags.txt | 1 + 22 files changed, 332 insertions(+), 65 deletions(-) delete mode 100644 basis/core-foundation/run-loop/thread/summary.txt delete mode 100644 basis/core-foundation/run-loop/thread/thread.factor rename basis/{core-foundation/run-loop/thread => io/unix/multiplexers/epoll}/authors.txt (100%) mode change 100644 => 100755 create mode 100644 basis/io/unix/multiplexers/epoll/epoll.factor rename basis/{core-foundation/run-loop/thread => io/unix/multiplexers/epoll}/tags.txt (100%) create mode 100755 basis/io/unix/multiplexers/kqueue/authors.txt create mode 100644 basis/io/unix/multiplexers/kqueue/kqueue.factor create mode 100644 basis/io/unix/multiplexers/kqueue/tags.txt create mode 100644 basis/io/unix/multiplexers/multiplexers.factor create mode 100644 basis/io/unix/multiplexers/run-loop/run-loop.factor create mode 100644 basis/io/unix/multiplexers/run-loop/tags.txt create mode 100755 basis/io/unix/multiplexers/select/authors.txt create mode 100644 basis/io/unix/multiplexers/select/select.factor create mode 100644 basis/io/unix/multiplexers/select/tags.txt diff --git a/basis/core-foundation/core-foundation.factor b/basis/core-foundation/core-foundation.factor index 48d7b7e483..40dd4710a1 100644 --- a/basis/core-foundation/core-foundation.factor +++ b/basis/core-foundation/core-foundation.factor @@ -1,8 +1,8 @@ ! Copyright (C) 2006, 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: alien alien.c-types alien.strings alien.syntax kernel -math sequences io.encodings.utf8 destructors accessors -combinators byte-arrays ; +math math.bitwise sequences io.encodings.utf8 destructors +accessors combinators byte-arrays ; IN: core-foundation TYPEDEF: void* CFAllocatorRef @@ -195,11 +195,22 @@ FUNCTION: CFFileDescriptorRef CFFileDescriptorCreate ( CFFileDescriptorContext* context ) ; +: kCFFileDescriptorReadCallBack 1 ; inline +: kCFFileDescriptorWriteCallBack 2 ; inline + FUNCTION: void CFFileDescriptorEnableCallBacks ( CFFileDescriptorRef f, CFOptionFlags callBackTypes ) ; +: enable-all-callbacks ( fd -- ) + { kCFFileDescriptorReadCallBack kCFFileDescriptorWriteCallBack } flags + CFFileDescriptorEnableCallBacks ; + +: ( fd callback -- handle ) + [ f swap ] [ t swap ] bi* f CFFileDescriptorCreate + [ "CFFileDescriptorCreate failed" throw ] unless* ; + : load-framework ( name -- ) dup [ CFBundleLoadExecutable drop diff --git a/basis/core-foundation/fsevents/fsevents.factor b/basis/core-foundation/fsevents/fsevents.factor index b3c1444043..67c2dcfa35 100644 --- a/basis/core-foundation/fsevents/fsevents.factor +++ b/basis/core-foundation/fsevents/fsevents.factor @@ -3,10 +3,10 @@ USING: alien alien.c-types alien.strings alien.syntax kernel math sequences namespaces make assocs init accessors continuations combinators core-foundation -core-foundation.run-loop core-foundation.run-loop.thread -io.encodings.utf8 destructors locals arrays -specialized-arrays.direct.alien specialized-arrays.direct.int -specialized-arrays.direct.longlong ; +core-foundation.run-loop io.encodings.utf8 destructors locals +arrays specialized-arrays.direct.alien +specialized-arrays.direct.int specialized-arrays.direct.longlong +; IN: core-foundation.fsevents : kFSEventStreamCreateFlagUseCFTypes 2 ; inline diff --git a/basis/core-foundation/run-loop/run-loop.factor b/basis/core-foundation/run-loop/run-loop.factor index 39f4101301..d254bf3adc 100644 --- a/basis/core-foundation/run-loop/run-loop.factor +++ b/basis/core-foundation/run-loop/run-loop.factor @@ -32,6 +32,12 @@ FUNCTION: void CFRunLoopAddSource ( CFStringRef mode ) ; +FUNCTION: void CFRunLoopRemoveSource ( + CFRunLoopRef rl, + CFRunLoopSourceRef source, + CFStringRef mode +) ; + : CFRunLoopDefaultMode ( -- alien ) #! Ugly, but we don't have static NSStrings \ CFRunLoopDefaultMode get-global dup expired? [ diff --git a/basis/core-foundation/run-loop/thread/summary.txt b/basis/core-foundation/run-loop/thread/summary.txt deleted file mode 100644 index e5818b3d78..0000000000 --- a/basis/core-foundation/run-loop/thread/summary.txt +++ /dev/null @@ -1 +0,0 @@ -Vocabulary with init hook for running CoreFoundation event loop diff --git a/basis/core-foundation/run-loop/thread/thread.factor b/basis/core-foundation/run-loop/thread/thread.factor deleted file mode 100644 index aeeff312cb..0000000000 --- a/basis/core-foundation/run-loop/thread/thread.factor +++ /dev/null @@ -1,16 +0,0 @@ -! Copyright (C) 2008 Slava Pestov -! See http://factorcode.org/license.txt for BSD license. -USING: calendar core-foundation.run-loop init kernel threads ; -IN: core-foundation.run-loop.thread - -! Load this vocabulary if you need a run loop running. - -: run-loop-thread ( -- ) - CFRunLoopDefaultMode 0 f CFRunLoopRunInMode - kCFRunLoopRunHandledSource = [ 1 seconds sleep ] unless - run-loop-thread ; - -: start-run-loop-thread ( -- ) - [ run-loop-thread t ] "CFRunLoop dispatcher" spawn-server drop ; - -[ start-run-loop-thread ] "core-foundation.run-loop.thread" add-init-hook diff --git a/basis/io/unix/backend/backend.factor b/basis/io/unix/backend/backend.factor index 954a0a61de..41bd03a58b 100644 --- a/basis/io/unix/backend/backend.factor +++ b/basis/io/unix/backend/backend.factor @@ -5,7 +5,7 @@ kernel.private math io.ports sequences strings sbufs threads unix vectors io.buffers io.backend io.encodings math.parser continuations system libc qualified namespaces make io.timeouts io.encodings.utf8 destructors accessors summary combinators -locals unix.time fry ; +locals unix.time fry io.unix.multiplexers ; QUALIFIED: io IN: io.unix.backend @@ -37,38 +37,6 @@ M: fd dispose M: fd handle-fd dup check-disposed fd>> ; -! I/O multiplexers -TUPLE: mx fd reads writes ; - -: new-mx ( class -- obj ) - new - H{ } clone >>reads - H{ } clone >>writes ; inline - -GENERIC: add-input-callback ( thread fd mx -- ) - -M: mx add-input-callback reads>> push-at ; - -GENERIC: add-output-callback ( thread fd mx -- ) - -M: mx add-output-callback writes>> push-at ; - -GENERIC: remove-input-callbacks ( fd mx -- callbacks ) - -M: mx remove-input-callbacks reads>> delete-at* drop ; - -GENERIC: remove-output-callbacks ( fd mx -- callbacks ) - -M: mx remove-output-callbacks writes>> delete-at* drop ; - -GENERIC: wait-for-events ( ms mx -- ) - -: input-available ( fd mx -- ) - reads>> delete-at* drop [ resume ] each ; - -: output-available ( fd mx -- ) - writes>> delete-at* drop [ resume ] each ; - M: fd cancel-operation ( fd -- ) dup disposed>> [ drop ] [ fd>> diff --git a/basis/io/unix/bsd/bsd.factor b/basis/io/unix/bsd/bsd.factor index e1583478db..83f063d713 100644 --- a/basis/io/unix/bsd/bsd.factor +++ b/basis/io/unix/bsd/bsd.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: namespaces system kernel accessors assocs continuations -unix io.backend io.unix.backend io.unix.kqueue ; +unix io.backend io.unix.backend io.unix.multiplexers +io.unix.multiplexers.kqueue ; IN: io.unix.bsd M: bsd init-io ( -- ) diff --git a/basis/io/unix/linux/linux.factor b/basis/io/unix/linux/linux.factor index be5b83f1b0..fd24e0ac02 100644 --- a/basis/io/unix/linux/linux.factor +++ b/basis/io/unix/linux/linux.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: kernel io.backend io.monitors io.unix.backend -io.unix.epoll io.unix.linux.monitors system namespaces ; +USING: kernel system namespaces io.backend io.unix.backend +io.unix.multiplexers io.unix.multiplexers.epoll ; IN: io.unix.linux M: linux init-io ( -- ) diff --git a/basis/io/unix/linux/monitors/monitors.factor b/basis/io/unix/linux/monitors/monitors.factor index f27d48c6b0..3964a25a04 100644 --- a/basis/io/unix/linux/monitors/monitors.factor +++ b/basis/io/unix/linux/monitors/monitors.factor @@ -2,10 +2,10 @@ ! See http://factorcode.org/license.txt for BSD license. USING: kernel io.backend io.monitors io.monitors.recursive io.files io.buffers io.monitors io.ports io.timeouts -io.unix.backend io.unix.select io.encodings.utf8 -unix.linux.inotify assocs namespaces make threads continuations -init math math.bitwise sets alien alien.strings alien.c-types -vocabs.loader accessors system hashtables destructors unix ; +io.unix.backend io.encodings.utf8 unix.linux.inotify assocs +namespaces make threads continuations init math math.bitwise +sets alien alien.strings alien.c-types vocabs.loader accessors +system hashtables destructors unix ; IN: io.unix.linux.monitors SYMBOL: watches diff --git a/basis/io/unix/macosx/macosx.factor b/basis/io/unix/macosx/macosx.factor index 388d266b48..75f42b7394 100644 --- a/basis/io/unix/macosx/macosx.factor +++ b/basis/io/unix/macosx/macosx.factor @@ -1,7 +1,10 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. +USING: io.backend system namespaces io.unix.multiplexers +io.unix.multiplexers.run-loop ; IN: io.unix.macosx -USING: io.unix.backend io.unix.bsd io.backend -namespaces system ; + +M: macosx init-io ( -- ) + mx set-global ; macosx set-io-backend diff --git a/basis/core-foundation/run-loop/thread/authors.txt b/basis/io/unix/multiplexers/epoll/authors.txt old mode 100644 new mode 100755 similarity index 100% rename from basis/core-foundation/run-loop/thread/authors.txt rename to basis/io/unix/multiplexers/epoll/authors.txt diff --git a/basis/io/unix/multiplexers/epoll/epoll.factor b/basis/io/unix/multiplexers/epoll/epoll.factor new file mode 100644 index 0000000000..08e20d4b95 --- /dev/null +++ b/basis/io/unix/multiplexers/epoll/epoll.factor @@ -0,0 +1,66 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors alien.c-types kernel destructors bit-arrays +sequences assocs struct-arrays math namespaces locals fry unix +unix.linux.epoll unix.time io.ports io.unix.backend +io.unix.multiplexers ; +IN: io.unix.multiplexers.epoll + +TUPLE: epoll-mx < mx events ; + +: max-events ( -- n ) + #! We read up to 256 events at a time. This is an arbitrary + #! constant... + 256 ; inline + +: ( -- mx ) + epoll-mx new-mx + max-events epoll_create dup io-error >>fd + max-events "epoll-event" >>events ; + +M: epoll-mx dispose fd>> close-file ; + +: make-event ( fd events -- event ) + "epoll-event" + [ set-epoll-event-events ] keep + [ set-epoll-event-fd ] keep ; + +:: do-epoll-ctl ( fd mx what events -- ) + mx fd>> what fd fd events make-event epoll_ctl io-error ; + +: do-epoll-add ( fd mx events -- ) + EPOLL_CTL_ADD swap EPOLLONESHOT bitor do-epoll-ctl ; + +: do-epoll-del ( fd mx events -- ) + EPOLL_CTL_DEL swap do-epoll-ctl ; + +M: epoll-mx add-input-callback ( thread fd mx -- ) + [ EPOLLIN do-epoll-add ] [ call-next-method ] 2bi ; + +M: epoll-mx add-output-callback ( thread fd mx -- ) + [ EPOLLOUT do-epoll-add ] [ call-next-method ] 2bi ; + +M: epoll-mx remove-input-callbacks ( fd mx -- seq ) + 2dup reads>> key? [ + [ call-next-method ] [ EPOLLIN do-epoll-del ] 2bi + ] [ 2drop f ] if ; + +M: epoll-mx remove-output-callbacks ( fd mx -- seq ) + 2dup writes>> key? [ + [ EPOLLOUT do-epoll-del ] [ call-next-method ] 2bi + ] [ 2drop f ] if ; + +: wait-event ( mx us -- n ) + [ [ fd>> ] [ events>> ] bi [ underlying>> ] [ length ] bi ] [ 1000 /i ] bi* + epoll_wait multiplexer-error ; + +: handle-event ( event mx -- ) + [ epoll-event-fd ] dip + [ EPOLLIN EPOLLOUT bitor do-epoll-del ] + [ input-available ] [ output-available ] 2tri ; + +: handle-events ( mx n -- ) + [ dup events>> ] dip head-slice swap '[ _ handle-event ] each ; + +M: epoll-mx wait-for-events ( us mx -- ) + swap 60000000 or dupd wait-event handle-events ; diff --git a/basis/core-foundation/run-loop/thread/tags.txt b/basis/io/unix/multiplexers/epoll/tags.txt similarity index 100% rename from basis/core-foundation/run-loop/thread/tags.txt rename to basis/io/unix/multiplexers/epoll/tags.txt diff --git a/basis/io/unix/multiplexers/kqueue/authors.txt b/basis/io/unix/multiplexers/kqueue/authors.txt new file mode 100755 index 0000000000..1901f27a24 --- /dev/null +++ b/basis/io/unix/multiplexers/kqueue/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/basis/io/unix/multiplexers/kqueue/kqueue.factor b/basis/io/unix/multiplexers/kqueue/kqueue.factor new file mode 100644 index 0000000000..a66e86a6a7 --- /dev/null +++ b/basis/io/unix/multiplexers/kqueue/kqueue.factor @@ -0,0 +1,76 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors alien.c-types combinators destructors +io.unix.backend kernel math.bitwise sequences struct-arrays unix +unix.kqueue unix.time assocs io.unix.multiplexers ; +IN: io.unix.multiplexers.kqueue + +TUPLE: kqueue-mx < mx events ; + +: max-events ( -- n ) + #! We read up to 256 events at a time. This is an arbitrary + #! constant... + 256 ; inline + +: ( -- mx ) + kqueue-mx new-mx + kqueue dup io-error >>fd + max-events "kevent" >>events ; + +M: kqueue-mx dispose fd>> close-file ; + +: make-kevent ( fd filter flags -- event ) + "kevent" + [ set-kevent-flags ] keep + [ set-kevent-filter ] keep + [ set-kevent-ident ] keep ; + +: register-kevent ( kevent mx -- ) + fd>> swap 1 f 0 f kevent io-error ; + +M: kqueue-mx add-input-callback ( thread fd mx -- ) + [ call-next-method ] [ + [ EVFILT_READ { EV_ADD EV_ONESHOT } flags make-kevent ] dip + register-kevent + ] 2bi ; + +M: kqueue-mx add-output-callback ( thread fd mx -- ) + [ call-next-method ] [ + [ EVFILT_WRITE { EV_ADD EV_ONESHOT } flags make-kevent ] dip + register-kevent + ] 2bi ; + +M: kqueue-mx remove-input-callbacks ( fd mx -- seq ) + 2dup reads>> key? [ + [ call-next-method ] [ + [ EVFILT_READ EV_DELETE make-kevent ] dip + register-kevent + ] 2bi + ] [ 2drop f ] if ; + +M: kqueue-mx remove-output-callbacks ( fd mx -- seq ) + 2dup writes>> key? [ + [ + [ EVFILT_WRITE EV_DELETE make-kevent ] dip + register-kevent + ] [ call-next-method ] 2bi + ] [ 2drop f ] if ; + +: wait-kevent ( mx timespec -- n ) + [ + [ fd>> f 0 ] + [ events>> [ underlying>> ] [ length ] bi ] bi + ] dip kevent multiplexer-error ; + +: handle-kevent ( mx kevent -- ) + [ kevent-ident swap ] [ kevent-filter ] bi { + { EVFILT_READ [ input-available ] } + { EVFILT_WRITE [ output-available ] } + } case ; + +: handle-kevents ( mx n -- ) + [ dup events>> ] dip head-slice [ handle-kevent ] with each ; + +M: kqueue-mx wait-for-events ( us mx -- ) + swap dup [ make-timespec ] when + dupd wait-kevent handle-kevents ; diff --git a/basis/io/unix/multiplexers/kqueue/tags.txt b/basis/io/unix/multiplexers/kqueue/tags.txt new file mode 100644 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/io/unix/multiplexers/kqueue/tags.txt @@ -0,0 +1 @@ +unportable diff --git a/basis/io/unix/multiplexers/multiplexers.factor b/basis/io/unix/multiplexers/multiplexers.factor new file mode 100644 index 0000000000..1c9fb134e7 --- /dev/null +++ b/basis/io/unix/multiplexers/multiplexers.factor @@ -0,0 +1,35 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel accessors assocs sequences threads ; +IN: io.unix.multiplexers + +TUPLE: mx fd reads writes ; + +: new-mx ( class -- obj ) + new + H{ } clone >>reads + H{ } clone >>writes ; inline + +GENERIC: add-input-callback ( thread fd mx -- ) + +M: mx add-input-callback reads>> push-at ; + +GENERIC: add-output-callback ( thread fd mx -- ) + +M: mx add-output-callback writes>> push-at ; + +GENERIC: remove-input-callbacks ( fd mx -- callbacks ) + +M: mx remove-input-callbacks reads>> delete-at* drop ; + +GENERIC: remove-output-callbacks ( fd mx -- callbacks ) + +M: mx remove-output-callbacks writes>> delete-at* drop ; + +GENERIC: wait-for-events ( ms mx -- ) + +: input-available ( fd mx -- ) + reads>> delete-at* drop [ resume ] each ; + +: output-available ( fd mx -- ) + writes>> delete-at* drop [ resume ] each ; diff --git a/basis/io/unix/multiplexers/run-loop/run-loop.factor b/basis/io/unix/multiplexers/run-loop/run-loop.factor new file mode 100644 index 0000000000..baaf910f37 --- /dev/null +++ b/basis/io/unix/multiplexers/run-loop/run-loop.factor @@ -0,0 +1,57 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel namespaces math accessors threads alien locals +destructors combinators core-foundation core-foundation.run-loop +io.unix.multiplexers io.unix.multiplexers.kqueue ; +IN: io.unix.multiplexers.run-loop + +TUPLE: run-loop-mx kqueue-mx fd source ; + +: kqueue-callback ( -- callback ) + "void" { "CFFileDescriptorRef" "CFOptionFlags" "void*" } + "cdecl" [ + 3drop + 0 mx get kqueue-mx>> wait-for-events + mx get fd>> enable-all-callbacks + yield + ] + alien-callback ; + +SYMBOL: kqueue-run-loop-source + +: create-kqueue-source ( fd -- source ) + f swap 0 CFFileDescriptorCreateRunLoopSource ; + +: add-kqueue-to-run-loop ( mx -- ) + CFRunLoopGetMain swap source>> CFRunLoopDefaultMode CFRunLoopAddSource ; + +: remove-kqueue-from-run-loop ( source -- ) + CFRunLoopGetMain swap source>> CFRunLoopDefaultMode CFRunLoopRemoveSource ; + +: ( -- mx ) + [ + |dispose + dup fd>> kqueue-callback |dispose + dup create-kqueue-source run-loop-mx boa + dup add-kqueue-to-run-loop + ] with-destructors ; + +M: run-loop-mx dispose + [ + { + [ fd>> &dispose drop ] + [ source>> &dispose drop ] + [ remove-kqueue-from-run-loop ] + [ kqueue-mx>> &dispose drop ] + } cleave + ] with-destructors ; + +M: run-loop-mx add-input-callback kqueue-mx>> add-input-callback ; +M: run-loop-mx add-output-callback kqueue-mx>> add-output-callback ; +M: run-loop-mx remove-input-callbacks kqueue-mx>> remove-input-callbacks ; +M: run-loop-mx remove-output-callbacks kqueue-mx>> remove-output-callbacks ; + +M:: run-loop-mx wait-for-events ( us mx -- ) + mx fd>> enable-all-callbacks + CFRunLoopDefaultMode us [ 1000000 /f ] [ 60 ] if* t CFRunLoopRunInMode + kCFRunLoopRunHandledSource = [ 0 mx wait-for-events ] when ; diff --git a/basis/io/unix/multiplexers/run-loop/tags.txt b/basis/io/unix/multiplexers/run-loop/tags.txt new file mode 100644 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/io/unix/multiplexers/run-loop/tags.txt @@ -0,0 +1 @@ +unportable diff --git a/basis/io/unix/multiplexers/select/authors.txt b/basis/io/unix/multiplexers/select/authors.txt new file mode 100755 index 0000000000..1901f27a24 --- /dev/null +++ b/basis/io/unix/multiplexers/select/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/basis/io/unix/multiplexers/select/select.factor b/basis/io/unix/multiplexers/select/select.factor new file mode 100644 index 0000000000..915daac2d3 --- /dev/null +++ b/basis/io/unix/multiplexers/select/select.factor @@ -0,0 +1,56 @@ +! Copyright (C) 2004, 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien.c-types kernel bit-arrays sequences assocs unix +math namespaces accessors math.order locals unix.time fry +io.ports io.unix.backend io.unix.multiplexers ; +IN: io.unix.multiplexers.select + +TUPLE: select-mx < mx read-fdset write-fdset ; + +! Factor's bit-arrays are an array of bytes, OS X expects +! FD_SET to be an array of cells, so we have to account for +! byte order differences on big endian platforms +: munge ( i -- i' ) + little-endian? [ BIN: 11000 bitxor ] unless ; inline + +: ( -- mx ) + select-mx new-mx + FD_SETSIZE 8 * >>read-fdset + FD_SETSIZE 8 * >>write-fdset ; + +: clear-nth ( n seq -- ? ) + [ nth ] [ [ f ] 2dip set-nth ] 2bi ; + +:: check-fd ( fd fdset mx quot -- ) + fd munge fdset clear-nth [ fd mx quot call ] when ; inline + +: check-fdset ( fds fdset mx quot -- ) + [ check-fd ] 3curry each ; inline + +: init-fdset ( fds fdset -- ) + '[ t swap munge _ set-nth ] each ; + +: read-fdset/tasks ( mx -- seq fdset ) + [ reads>> keys ] [ read-fdset>> ] bi ; + +: write-fdset/tasks ( mx -- seq fdset ) + [ writes>> keys ] [ write-fdset>> ] bi ; + +: max-fd ( assoc -- n ) + dup assoc-empty? [ drop 0 ] [ keys supremum ] if ; + +: num-fds ( mx -- n ) + [ reads>> max-fd ] [ writes>> max-fd ] bi max 1+ ; + +: init-fdsets ( mx -- nfds read write except ) + [ num-fds ] + [ read-fdset/tasks [ init-fdset ] [ underlying>> ] bi ] + [ write-fdset/tasks [ init-fdset ] [ underlying>> ] bi ] tri + f ; + +M:: select-mx wait-for-events ( us mx -- ) + mx + [ init-fdsets us dup [ make-timeval ] when select multiplexer-error drop ] + [ [ read-fdset/tasks ] keep [ input-available ] check-fdset ] + [ [ write-fdset/tasks ] keep [ output-available ] check-fdset ] + tri ; diff --git a/basis/io/unix/multiplexers/select/tags.txt b/basis/io/unix/multiplexers/select/tags.txt new file mode 100644 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/io/unix/multiplexers/select/tags.txt @@ -0,0 +1 @@ +unportable