Implement new box data type, fix various bugs, add status parameter for suspend, threads. now prints thread state

db4
Slava Pestov 2008-02-19 14:38:02 -06:00
parent cb1b19fa9b
commit 37e0e28f35
24 changed files with 218 additions and 111 deletions

38
core/boxes/boxes-docs.factor Executable file
View File

@ -0,0 +1,38 @@
USING: help.markup help.syntax kernel ;
IN: boxes
HELP: box
{ $class-description "A data type holding a single value in the " { $link box-value } " slot. The " { $link box-full? } " slot indicates if the value is set." } ;
HELP: <box>
{ $values { "box" box } }
{ $description "Creates a new empty box." } ;
HELP: >box
{ $values { "value" object } { "box" box } }
{ $description "Stores a value into a box." }
{ $errors "Throws an error if the box is full." } ;
HELP: box>
{ $values { "box" box } { "value" "the value of the box" } }
{ $description "Removes a value from a box." }
{ $errors "Throws an error if the box is empty." } ;
HELP: ?box
{ $values { "box" box } { "value" "the value of the box or " { $link f } } { "?" "a boolean" } }
{ $description "If the box is full, removes the value from the box and pushes " { $link t } ". If the box is empty pushes " { $snippet "f f" } "." } ;
ARTICLE: "boxes" "Boxes"
"A " { $emphasis "box" } " is a container which can either be empty or hold a single value."
{ $subsection box }
"Creating an empty box:"
{ $subsection <box> }
"Testing if a box is full:"
{ $subsection box-full? }
"Storing a value and removing a value from a box:"
{ $subsection >box }
{ $subsection box> }
"Safely removing a value:"
{ $subsection ?box } ;
ABOUT: "boxes"

24
core/boxes/boxes-tests.factor Executable file
View File

@ -0,0 +1,24 @@
IN: temporary
USING: boxes namespaces tools.test ;
[ ] [ <box> "b" set ] unit-test
[ ] [ 3 "b" get >box ] unit-test
[ t ] [ "b" get box-full? ] unit-test
[ 4 "b" >box ] must-fail
[ 3 ] [ "b" get box> ] unit-test
[ f ] [ "b" get box-full? ] unit-test
[ "b" get box> ] must-fail
[ f f ] [ "b" get ?box ] unit-test
[ ] [ 12 "b" get >box ] unit-test
[ 12 t ] [ "b" get ?box ] unit-test
[ f ] [ "b" get box-full? ] unit-test

21
core/boxes/boxes.factor Executable file
View File

@ -0,0 +1,21 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel ;
IN: boxes
TUPLE: box value full? ;
: <box> ( -- box ) box construct-empty ;
: >box ( value box -- )
dup box-full? [ "Box already has a value" throw ] when
t over set-box-full?
set-box-value ;
: box> ( box -- value )
dup box-full? [ "Box empty" throw ] unless
dup box-value f pick set-box-value
f rot set-box-full? ;
: ?box ( box -- value/f ? )
dup box-full? [ box> t ] [ drop f f ] if ;

View File

@ -1,4 +1,4 @@
! Copyright (C) 2003, 2007 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays hashtables io kernel math memory namespaces USING: arrays hashtables io kernel math memory namespaces
parser sequences strings io.styles io.streams.lines parser sequences strings io.styles io.streams.lines

View File

@ -409,6 +409,7 @@ SYMBOL: interactive-vocabs
"tools.memory" "tools.memory"
"tools.profiler" "tools.profiler"
"tools.test" "tools.test"
"tools.threads"
"tools.time" "tools.time"
"vocabs" "vocabs"
"vocabs.loader" "vocabs.loader"

View File

@ -1,6 +1,6 @@
USING: help.markup help.syntax kernel kernel.private io USING: help.markup help.syntax kernel kernel.private io
threads.private continuations dlists init quotations strings threads.private continuations dlists init quotations strings
assocs heaps ; assocs heaps boxes ;
IN: threads IN: threads
ARTICLE: "threads-start/stop" "Starting and stopping threads" ARTICLE: "threads-start/stop" "Starting and stopping threads"
@ -61,7 +61,7 @@ HELP: thread
{ { $link thread-id } " - a unique identifier assigned to each thread." } { { $link thread-id } " - a unique identifier assigned to each thread." }
{ { $link thread-name } " - the name passed to " { $link spawn } "." } { { $link thread-name } " - the name passed to " { $link spawn } "." }
{ { $link thread-quot } " - the initial quotation passed to " { $link spawn } "." } { { $link thread-quot } " - the initial quotation passed to " { $link spawn } "." }
{ { $link thread-continuation } " - if the thread is waiting to run, the saved thread context. If the thread is currently running, will be " { $link f } "." } { { $link thread-continuation } " - a " { $link box } "; if the thread is ready to run, the box holds the continuation, otherwise it is empty." }
{ { $link thread-registered? } " - a boolean indicating whether the thread is eligible to run or not. Spawning a thread with " { $link (spawn) } " sets this flag and " { $link stop } " clears it." } { { $link thread-registered? } " - a boolean indicating whether the thread is eligible to run or not. Spawning a thread with " { $link (spawn) } " sets this flag and " { $link stop } " clears it." }
} }
} ; } ;

View File

@ -12,5 +12,5 @@ yield
[ "hey" sleep ] must-fail [ "hey" sleep ] must-fail
[ 3 ] [ [ 3 ] [
[ 3 swap resume-with ] suspend [ 3 swap resume-with ] "Test suspend" suspend
] unit-test ] unit-test

View File

@ -4,14 +4,15 @@
IN: threads IN: threads
USING: arrays hashtables heaps kernel kernel.private math USING: arrays hashtables heaps kernel kernel.private math
namespaces sequences vectors continuations continuations.private namespaces sequences vectors continuations continuations.private
dlists assocs system combinators debugger prettyprint io init ; dlists assocs system combinators debugger prettyprint io init
boxes ;
SYMBOL: initial-thread SYMBOL: initial-thread
TUPLE: thread TUPLE: thread
name quot error-handler name quot error-handler
id registered? id registered?
continuation continuation state
mailbox variables ; mailbox variables ;
: self ( -- thread ) 40 getenv ; inline : self ( -- thread ) 40 getenv ; inline
@ -61,11 +62,12 @@ threads global [ H{ } assoc-like ] change-at
PRIVATE> PRIVATE>
: <thread> ( quot name error-handler -- thread ) : <thread> ( quot name error-handler -- thread )
\ thread counter { \ thread counter <box> {
set-thread-quot set-thread-quot
set-thread-name set-thread-name
set-thread-error-handler set-thread-error-handler
set-thread-id set-thread-id
set-thread-continuation
} \ thread construct ; } \ thread construct ;
: run-queue 42 getenv ; : run-queue 42 getenv ;
@ -99,8 +101,8 @@ PRIVATE>
wake-up wake-up
run-queue pop-back run-queue pop-back
dup array? [ first2 ] [ f swap ] if dup set-self dup array? [ first2 ] [ f swap ] if dup set-self
dup thread-continuation f over set-thread-state
f rot set-thread-continuation thread-continuation box>
continue-with continue-with
] if* ; ] if* ;
@ -116,15 +118,19 @@ PRIVATE>
: stop ( -- ) : stop ( -- )
self unregister-thread next ; self unregister-thread next ;
: suspend ( quot -- obj ) : suspend ( quot state -- obj )
[ [
>r self [ set-thread-continuation ] keep r> call next self thread-continuation >box
] curry callcc1 ; inline self set-thread-state
self swap call next
] callcc1 2nip ; inline
: yield ( -- ) [ resume ] suspend drop ; : yield ( -- ) [ resume ] "yield" suspend drop ;
: sleep ( ms -- ) : sleep ( ms -- )
>fixnum millis + [ schedule-sleep ] curry suspend drop ; >fixnum millis +
[ schedule-sleep ] curry
"sleep" suspend drop ;
: (spawn) ( thread -- ) : (spawn) ( thread -- )
[ [
@ -137,7 +143,7 @@ PRIVATE>
>r { } set-datastack r> >r { } set-datastack r>
thread-quot [ call stop ] call-clear thread-quot [ call stop ] call-clear
] 1 (throw) ] 1 (throw)
] suspend 2drop ; ] "spawn" suspend 2drop ;
: spawn ( quot name -- thread ) : spawn ( quot name -- thread )
[ [
@ -170,7 +176,7 @@ PRIVATE>
<min-heap> 43 setenv <min-heap> 43 setenv
initial-thread global initial-thread global
[ drop f "Initial" [ die ] <thread> ] cache [ drop f "Initial" [ die ] <thread> ] cache
f over set-thread-continuation <box> over set-thread-continuation
f over set-thread-registered? f over set-thread-registered?
dup register-thread dup register-thread
set-self ; set-self ;

View File

@ -9,5 +9,5 @@ IN: concurrency.conditions
: notify-all ( dlist -- ) : notify-all ( dlist -- )
[ second resume ] dlist-slurp yield ; [ second resume ] dlist-slurp yield ;
: wait ( queue timeout -- ) : wait ( queue timeout status -- )
[ 2array swap push-front ] suspend 3drop ; inline >r [ 2array swap push-front ] r> suspend 3drop ; inline

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel threads ; USING: kernel threads boxes ;
IN: concurrency.exchangers IN: concurrency.exchangers
! Motivated by ! Motivated by
@ -9,18 +9,13 @@ IN: concurrency.exchangers
TUPLE: exchanger thread object ; TUPLE: exchanger thread object ;
: <exchanger> ( -- exchanger ) : <exchanger> ( -- exchanger )
f f exchanger construct-boa ; <box> <box> exchanger construct-boa ;
: pop-object ( exchanger -- obj )
dup exchanger-object f rot set-exchanger-object ;
: pop-thread ( exchanger -- thread )
dup exchanger-thread f rot set-exchanger-thread ;
: exchange ( obj exchanger -- newobj ) : exchange ( obj exchanger -- newobj )
dup exchanger-thread [ dup exchanger-thread box-full? [
dup pop-object >r pop-thread resume-with r> dup exchanger-object box>
>r exchanger-thread box> resume-with r>
] [ ] [
[ set-exchanger-object ] keep [ exchanger-object >box ] keep
[ set-exchanger-thread ] curry suspend [ exchanger-thread >box ] curry "Exchange wait" suspend
] if ; ] if ;

View File

@ -17,7 +17,7 @@ TUPLE: lock threads owner reentrant? ;
: acquire-lock ( lock timeout -- ) : acquire-lock ( lock timeout -- )
over lock-owner over lock-owner
[ 2dup >r lock-threads r> wait ] when drop [ 2dup >r lock-threads r> "lock" wait ] when drop
self swap set-lock-owner ; self swap set-lock-owner ;
: release-lock ( lock -- ) : release-lock ( lock -- )
@ -54,7 +54,7 @@ TUPLE: rw-lock readers writers reader# writer ;
: acquire-read-lock ( lock timeout -- ) : acquire-read-lock ( lock timeout -- )
over rw-lock-writer over rw-lock-writer
[ 2dup >r rw-lock-readers r> wait ] when drop [ 2dup >r rw-lock-readers r> "read lock" wait ] when drop
dup rw-lock-reader# 1+ swap set-rw-lock-reader# ; dup rw-lock-reader# 1+ swap set-rw-lock-reader# ;
: notify-writer ( lock -- ) : notify-writer ( lock -- )
@ -66,7 +66,7 @@ TUPLE: rw-lock readers writers reader# writer ;
: acquire-write-lock ( lock timeout -- ) : acquire-write-lock ( lock timeout -- )
over rw-lock-writer pick rw-lock-reader# 0 > or over rw-lock-writer pick rw-lock-reader# 0 > or
[ 2dup >r rw-lock-writers r> wait ] when drop [ 2dup >r rw-lock-writers r> "write lock" wait ] when drop
self swap set-rw-lock-writer ; self swap set-rw-lock-writer ;
: release-write-lock ( lock -- ) : release-write-lock ( lock -- )

View File

@ -73,18 +73,21 @@ MATCH-VARS: ?from ?to ?value ;
SYMBOL: increment SYMBOL: increment
SYMBOL: decrement SYMBOL: decrement
SYMBOL: value SYMBOL: value
SYMBOL: exit
: counter ( value -- value ) : counter ( value -- value ? )
receive { receive {
{ { increment ?value } [ ?value + ] } { { increment ?value } [ ?value + t ] }
{ { decrement ?value } [ ?value - ] } { { decrement ?value } [ ?value - t ] }
{ { value ?from } [ dup ?from send ] } { { value ?from } [ dup ?from send t ] }
{ exit [ f ] }
} match-cond ; } match-cond ;
[ -5 ] [ [ -5 ] [
[ 0 [ t ] [ counter ] [ ] while ] "Counter" spawn [ 0 [ counter ] [ ] [ ] while ] "Counter" spawn "counter" set
{ increment 10 } over send { increment 10 } "counter" get send
{ decrement 15 } over send { decrement 15 } "counter" get send
[ value , self , ] { } make swap send [ value , self , ] { } make "counter" get send
receive receive
exit "counter" get send
] unit-test ] unit-test

View File

@ -26,12 +26,14 @@ TUPLE: mailbox threads data ;
2over mailbox-data dlist-contains? [ 2over mailbox-data dlist-contains? [
3drop 3drop
] [ ] [
2dup >r mailbox-threads r> wait block-unless-pred 2dup >r mailbox-threads r> "mailbox" wait
block-unless-pred
] if ; inline ] if ; inline
: block-if-empty ( mailbox timeout -- mailbox ) : block-if-empty ( mailbox timeout -- mailbox )
over mailbox-empty? [ over mailbox-empty? [
2dup >r mailbox-threads r> wait block-if-empty 2dup >r mailbox-threads r> "mailbox" wait
block-if-empty
] [ ] [
drop drop
] if ; ] if ;

View File

@ -11,7 +11,7 @@ TUPLE: semaphore count threads ;
<dlist> semaphore construct-boa ; <dlist> semaphore construct-boa ;
: wait-to-acquire ( semaphore timeout -- ) : wait-to-acquire ( semaphore timeout -- )
>r semaphore-threads r> wait ; >r semaphore-threads r> "semaphore" wait ;
: acquire ( semaphore timeout -- ) : acquire ( semaphore timeout -- )
dup semaphore-count zero? [ dup semaphore-count zero? [

View File

@ -161,6 +161,7 @@ ARTICLE: "collections" "Collections"
{ $subsection "hashtables" } { $subsection "hashtables" }
{ $subsection "alists" } { $subsection "alists" }
{ $heading "Other collections" } { $heading "Other collections" }
{ $subsection "boxes" }
{ $subsection "dlists" } { $subsection "dlists" }
{ $subsection "heaps" } { $subsection "heaps" }
{ $subsection "graphs" } { $subsection "graphs" }

View File

@ -83,7 +83,10 @@ HOOK: run-process* io-backend ( desc -- handle )
: wait-for-process ( process -- status ) : wait-for-process ( process -- status )
[ [
dup process-handle dup process-handle
[ dup [ processes get at push ] curry suspend drop ] when [
dup [ processes get at push ] curry
"process" suspend drop
] when
dup process-killed? dup process-killed?
[ "Process was killed" throw ] [ process-status ] if [ "Process was killed" throw ] [ process-status ] if
] with-timeout ; ] with-timeout ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.backend kernel continuations namespaces sequences USING: io.backend kernel continuations namespaces sequences
assocs hashtables sorting arrays threads ; assocs hashtables sorting arrays threads boxes ;
IN: io.monitors IN: io.monitors
<PRIVATE <PRIVATE
@ -35,24 +35,21 @@ M: monitor dispose
TUPLE: simple-monitor handle callback ; TUPLE: simple-monitor handle callback ;
: <simple-monitor> ( handle -- simple-monitor ) : <simple-monitor> ( handle -- simple-monitor )
f (monitor) { f (monitor) <box> {
set-simple-monitor-handle set-simple-monitor-handle
set-delegate set-delegate
set-simple-monitor-callback
} simple-monitor construct ; } simple-monitor construct ;
: construct-simple-monitor ( handle class -- simple-monitor ) : construct-simple-monitor ( handle class -- simple-monitor )
>r <simple-monitor> r> construct-delegate ; inline >r <simple-monitor> r> construct-delegate ; inline
: notify-callback ( simple-monitor -- ) : notify-callback ( simple-monitor -- )
dup simple-monitor-callback simple-monitor-callback ?box [ resume ] [ drop ] if ;
f rot set-simple-monitor-callback
[ resume ] when* ;
M: simple-monitor fill-queue ( monitor -- ) M: simple-monitor fill-queue ( monitor -- )
dup simple-monitor-callback [ [ swap simple-monitor-callback >box ]
"Cannot wait for changes on the same file from multiple threads" throw "monitor" suspend drop
] when
[ swap set-simple-monitor-callback ] suspend drop
check-monitor ; check-monitor ;
M: simple-monitor dispose ( monitor -- ) M: simple-monitor dispose ( monitor -- )

View File

@ -3,10 +3,17 @@
USING: io io.sockets io.files logging continuations kernel USING: io io.sockets io.files logging continuations kernel
math math.parser namespaces parser sequences strings math math.parser namespaces parser sequences strings
prettyprint debugger quotations calendar prettyprint debugger quotations calendar
threads concurrency.combinators ; threads concurrency.combinators assocs ;
IN: io.server IN: io.server
SYMBOL: servers
<PRIVATE
: spawn-vars ( quot vars name -- )
>r [ dup get ] H{ } map>assoc [ swap bind ] 2curry r>
spawn drop ;
LOG: accepted-connection NOTICE LOG: accepted-connection NOTICE
: with-client ( client quot -- ) : with-client ( client quot -- )
@ -15,23 +22,21 @@ LOG: accepted-connection NOTICE
with-stream* with-stream*
] curry with-disposal ; inline ] curry with-disposal ; inline
\ with-client NOTICE add-error-logging \ with-client DEBUG add-error-logging
: accept-loop ( server quot -- ) : accept-loop ( server quot -- )
[ [
>r accept r> [ with-client ] 2curry >r accept r> [ with-client ] 2curry
"Client" spawn drop { log-service servers } "Client" spawn-vars
] 2keep accept-loop ; inline ] 2keep accept-loop ; inline
: server-loop ( server quot -- ) : server-loop ( addrspec quot -- )
>r <server> dup servers get push r>
[ accept-loop ] curry with-disposal ; inline [ accept-loop ] curry with-disposal ; inline
SYMBOL: servers \ server-loop NOTICE add-error-logging
: spawn-server ( addrspec quot -- ) PRIVATE>
>r <server> dup servers get push r> server-loop ; inline
\ spawn-server NOTICE add-error-logging
: local-server ( port -- seq ) : local-server ( port -- seq )
"localhost" swap t resolve-host ; "localhost" swap t resolve-host ;
@ -40,17 +45,18 @@ SYMBOL: servers
f swap t resolve-host ; f swap t resolve-host ;
: with-server ( seq service quot -- ) : with-server ( seq service quot -- )
[ V{ } clone [
V{ } clone servers set servers [
[ spawn-server ] curry parallel-each [ server-loop ] curry with-logging
] curry with-logging ; inline ] with-variable
] 3curry parallel-each ; inline
: stop-server ( -- ) : stop-server ( -- )
servers get [ dispose ] each ; servers get [ dispose ] each ;
: received-datagram ( addrspec -- ) drop ; <PRIVATE
\ received-datagram NOTICE add-input-logging LOG: received-datagram NOTICE
: datagram-loop ( quot datagram -- ) : datagram-loop ( quot datagram -- )
[ [
@ -63,6 +69,8 @@ SYMBOL: servers
\ spawn-datagrams NOTICE add-input-logging \ spawn-datagrams NOTICE add-input-logging
PRIVATE>
: with-datagrams ( seq service quot -- ) : with-datagrams ( seq service quot -- )
[ [
[ swap spawn-datagrams ] curry parallel-each [ swap spawn-datagrams ] curry parallel-each

View File

@ -62,7 +62,7 @@ M: mx register-io-task ( task mx -- )
mx get-global register-io-task ; mx get-global register-io-task ;
: with-port-continuation ( port quot -- port ) : with-port-continuation ( port quot -- port )
[ suspend drop ] curry with-timeout ; inline [ "I/O" suspend drop ] curry with-timeout ; inline
M: mx unregister-io-task ( task mx -- ) M: mx unregister-io-task ( task mx -- )
fd/container delete-at drop ; fd/container delete-at drop ;

View File

@ -54,7 +54,7 @@ M: windows-nt-io add-completion ( handle -- )
<io-callback> swap <io-callback> swap
dup alien? [ "bad overlapped in save-callback" throw ] unless dup alien? [ "bad overlapped in save-callback" throw ] unless
io-hash get-global set-at io-hash get-global set-at
] suspend 3drop ; ] "I/O" suspend 3drop ;
: wait-for-overlapped ( ms -- overlapped ? ) : wait-for-overlapped ( ms -- overlapped ? )
>r master-completion-port get-global r> ! port ms >r master-completion-port get-global r> ! port ms

View File

@ -2,12 +2,13 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: tools.threads IN: tools.threads
USING: threads kernel prettyprint prettyprint.config USING: threads kernel prettyprint prettyprint.config
io io.styles sequences assocs namespaces sorting ; io io.styles sequences assocs namespaces sorting boxes ;
: thread. ( thread -- ) : thread. ( thread -- )
dup thread-id pprint-cell dup thread-id pprint-cell
dup thread-name pprint-cell dup thread-name pprint-cell
thread-continuation "Waiting" "Running" ? [ write ] with-cell ; thread-state [ "Waiting for " swap append ] [ "Running" ] if*
[ write ] with-cell ;
: threads. ( -- ) : threads. ( -- )
standard-table-style [ standard-table-style [

View File

@ -6,18 +6,27 @@ math.vectors models namespaces parser prettyprint quotations
sequences sequences.lib strings threads listener sequences sequences.lib strings threads listener
tuples ui.commands ui.gadgets ui.gadgets.editors tuples ui.commands ui.gadgets ui.gadgets.editors
ui.gadgets.presentations ui.gadgets.worlds ui.gestures ui.gadgets.presentations ui.gadgets.worlds ui.gestures
definitions ; definitions boxes ;
IN: ui.tools.interactor IN: ui.tools.interactor
TUPLE: interactor TUPLE: interactor
history output history output
thread quot busy? thread quot
help ; help ;
: interactor-continuation ( interactor -- continuation )
interactor-thread box-value
thread-continuation box-value ;
: interactor-busy? ( interactor -- ? )
interactor-thread box-full? not ;
: interactor-use ( interactor -- seq ) : interactor-use ( interactor -- seq )
use swap dup interactor-busy? [ drop f ] [
interactor-thread thread-continuation continuation-name use swap
assoc-stack ; interactor-continuation continuation-name
assoc-stack
] if ;
: init-caret-help ( interactor -- ) : init-caret-help ( interactor -- )
dup editor-caret 100 <delay> swap set-interactor-help ; dup editor-caret 100 <delay> swap set-interactor-help ;
@ -29,13 +38,13 @@ help ;
<source-editor> <source-editor>
interactor construct-editor interactor construct-editor
tuck set-interactor-output tuck set-interactor-output
<box> over set-interactor-thread
dup init-interactor-history dup init-interactor-history
dup init-caret-help ; dup init-caret-help ;
M: interactor graft* M: interactor graft*
dup delegate graft* dup delegate graft*
dup dup interactor-help add-connection dup interactor-help add-connection ;
f swap set-interactor-busy? ;
: word-at-loc ( loc interactor -- word ) : word-at-loc ( loc interactor -- word )
over [ over [
@ -65,17 +74,16 @@ M: interactor model-changed
over empty? [ 2drop ] [ interactor-history push-new ] if ; over empty? [ 2drop ] [ interactor-history push-new ] if ;
: interactor-continue ( obj interactor -- ) : interactor-continue ( obj interactor -- )
t over set-interactor-busy? interactor-thread box> resume-with ;
interactor-thread resume-with ;
: clear-input ( interactor -- ) gadget-model clear-doc ; : clear-input ( interactor -- ) gadget-model clear-doc ;
: interactor-finish ( interactor -- ) : interactor-finish ( interactor -- )
#! The in-thread is a kludge to make it infer. Stupid. #! The spawn is a kludge to make it infer. Stupid.
[ editor-string ] keep [ editor-string ] keep
[ interactor-input. ] 2keep [ interactor-input. ] 2keep
[ add-interactor-history ] keep [ add-interactor-history ] keep
[ clear-input ] curry in-thread ; [ clear-input ] curry "Clearing input" spawn drop ;
: interactor-eof ( interactor -- ) : interactor-eof ( interactor -- )
dup interactor-busy? [ dup interactor-busy? [
@ -88,12 +96,7 @@ M: interactor model-changed
] unless drop ; ] unless drop ;
: interactor-yield ( interactor -- obj ) : interactor-yield ( interactor -- obj )
! dup gadget-graft-state first [ [ interactor-thread >box ] curry "input" suspend ;
f over set-interactor-busy?
[ set-interactor-thread ] curry suspend ;
! ] [
! drop f
! ] if ;
M: interactor stream-readln M: interactor stream-readln
[ interactor-yield ] keep interactor-finish ?first ; [ interactor-yield ] keep interactor-finish ?first ;
@ -127,7 +130,7 @@ M: interactor stream-read-partial
[ [
drop parse-lines-interactive drop parse-lines-interactive
] [ ] [
>r f swap set-interactor-busy? drop r> 2nip
dup delegate unexpected-eof? [ drop f ] when dup delegate unexpected-eof? [ drop f ] when
] recover ; ] recover ;

View File

@ -28,11 +28,7 @@ TUPLE: listener-gadget input output stack ;
<scroller> "Input" <labelled-gadget> f track, ; <scroller> "Input" <labelled-gadget> f track, ;
: welcome. ( -- ) : welcome. ( -- )
"If this is your first time with the Factor UI," print "If this is your first time with Factor, please read the " print
"please read " write
"ui-tools" ($link) " and " write
"ui-listener" ($link) "." print nl
"If you are completely new to Factor, start with the " print
"cookbook" ($link) "." print nl ; "cookbook" ($link) "." print nl ;
M: listener-gadget focusable-child* M: listener-gadget focusable-child*
@ -45,7 +41,8 @@ M: listener-gadget tool-scroller
listener-gadget-output find-scroller ; listener-gadget-output find-scroller ;
: workspace-busy? ( workspace -- ? ) : workspace-busy? ( workspace -- ? )
workspace-listener listener-gadget-input interactor-busy? ; workspace-listener listener-gadget-input
interactor-busy? ;
: get-listener ( -- listener ) : get-listener ( -- listener )
[ workspace-busy? not ] get-workspace* workspace-listener ; [ workspace-busy? not ] get-workspace* workspace-listener ;
@ -81,8 +78,9 @@ M: listener-operation invoke-command ( target command -- )
listener-gadget-input interactor-eof ; listener-gadget-input interactor-eof ;
: clear-output ( listener -- ) : clear-output ( listener -- )
[ listener-gadget-output [ pane-clear ] curry ] keep listener-gadget-output pane-clear ;
(call-listener) ;
\ clear-output H{ { +listener+ t } } define-command
: clear-stack ( listener -- ) : clear-stack ( listener -- )
[ clear ] swap (call-listener) ; [ clear ] swap (call-listener) ;
@ -134,16 +132,16 @@ M: stack-display tool-scroller
] with-stream* ; ] with-stream* ;
: restart-listener ( listener -- ) : restart-listener ( listener -- )
[ listener-thread ] curry "Listener" spawn drop ; dup com-end dup clear-output
[ listener-thread ] curry
"Listener" spawn drop ;
: init-listener ( listener -- ) : init-listener ( listener -- )
f <model> swap set-listener-gadget-stack ; f <model> swap set-listener-gadget-stack ;
: <listener-gadget> ( -- gadget ) : <listener-gadget> ( -- gadget )
listener-gadget construct-empty listener-gadget construct-empty dup init-listener
dup init-listener [ listener-output, listener-input, ] { 0 1 } build-track ;
[ listener-output, listener-input, ] { 0 1 } build-track
dup restart-listener ;
: listener-help "ui-listener" help-window ; : listener-help "ui-listener" help-window ;
@ -160,3 +158,11 @@ listener-gadget "toolbar" f {
M: listener-gadget handle-gesture* ( gadget gesture delegate -- ? ) M: listener-gadget handle-gesture* ( gadget gesture delegate -- ? )
3dup drop swap find-workspace workspace-page handle-gesture 3dup drop swap find-workspace workspace-page handle-gesture
[ default-gesture-handler ] [ 3drop f ] if ; [ default-gesture-handler ] [ 3drop f ] if ;
M: listener-gadget graft*
dup delegate graft*
restart-listener ;
M: listener-gadget ungraft*
dup com-end
delegate ungraft* ;

View File

@ -131,12 +131,10 @@ SYMBOL: ui-hook
graft-queue [ notify ] dlist-slurp ; graft-queue [ notify ] dlist-slurp ;
: ui-step ( -- ) : ui-step ( -- )
[ [ do-timers ] assert-depth
do-timers [ notify-queued ] assert-depth
notify-queued [ layout-queued "a" set ] assert-depth
layout-queued [ "a" get redraw-worlds ] assert-depth ;
redraw-worlds
] assert-depth ;
: open-world-window ( world -- ) : open-world-window ( world -- )
dup pref-dim over set-gadget-dim dup relayout graft ui-step ; dup pref-dim over set-gadget-dim dup relayout graft ui-step ;