Implement new box data type, fix various bugs, add status parameter for suspend, threads. now prints thread state
parent
cb1b19fa9b
commit
37e0e28f35
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
@ -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 ;
|
||||
|
|
@ -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.
|
||||
USING: arrays hashtables io kernel math memory namespaces
|
||||
parser sequences strings io.styles io.streams.lines
|
||||
|
|
|
|||
|
|
@ -409,6 +409,7 @@ SYMBOL: interactive-vocabs
|
|||
"tools.memory"
|
||||
"tools.profiler"
|
||||
"tools.test"
|
||||
"tools.threads"
|
||||
"tools.time"
|
||||
"vocabs"
|
||||
"vocabs.loader"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
USING: help.markup help.syntax kernel kernel.private io
|
||||
threads.private continuations dlists init quotations strings
|
||||
assocs heaps ;
|
||||
assocs heaps boxes ;
|
||||
IN: 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-name } " - the name 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." }
|
||||
}
|
||||
} ;
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ yield
|
|||
[ "hey" sleep ] must-fail
|
||||
|
||||
[ 3 ] [
|
||||
[ 3 swap resume-with ] suspend
|
||||
[ 3 swap resume-with ] "Test suspend" suspend
|
||||
] unit-test
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@
|
|||
IN: threads
|
||||
USING: arrays hashtables heaps kernel kernel.private math
|
||||
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
|
||||
|
||||
TUPLE: thread
|
||||
name quot error-handler
|
||||
id registered?
|
||||
continuation
|
||||
continuation state
|
||||
mailbox variables ;
|
||||
|
||||
: self ( -- thread ) 40 getenv ; inline
|
||||
|
|
@ -61,11 +62,12 @@ threads global [ H{ } assoc-like ] change-at
|
|||
PRIVATE>
|
||||
|
||||
: <thread> ( quot name error-handler -- thread )
|
||||
\ thread counter {
|
||||
\ thread counter <box> {
|
||||
set-thread-quot
|
||||
set-thread-name
|
||||
set-thread-error-handler
|
||||
set-thread-id
|
||||
set-thread-continuation
|
||||
} \ thread construct ;
|
||||
|
||||
: run-queue 42 getenv ;
|
||||
|
|
@ -99,8 +101,8 @@ PRIVATE>
|
|||
wake-up
|
||||
run-queue pop-back
|
||||
dup array? [ first2 ] [ f swap ] if dup set-self
|
||||
dup thread-continuation
|
||||
f rot set-thread-continuation
|
||||
f over set-thread-state
|
||||
thread-continuation box>
|
||||
continue-with
|
||||
] if* ;
|
||||
|
||||
|
|
@ -116,15 +118,19 @@ PRIVATE>
|
|||
: stop ( -- )
|
||||
self unregister-thread next ;
|
||||
|
||||
: suspend ( quot -- obj )
|
||||
: suspend ( quot state -- obj )
|
||||
[
|
||||
>r self [ set-thread-continuation ] keep r> call next
|
||||
] curry callcc1 ; inline
|
||||
self thread-continuation >box
|
||||
self set-thread-state
|
||||
self swap call next
|
||||
] callcc1 2nip ; inline
|
||||
|
||||
: yield ( -- ) [ resume ] suspend drop ;
|
||||
: yield ( -- ) [ resume ] "yield" suspend drop ;
|
||||
|
||||
: sleep ( ms -- )
|
||||
>fixnum millis + [ schedule-sleep ] curry suspend drop ;
|
||||
>fixnum millis +
|
||||
[ schedule-sleep ] curry
|
||||
"sleep" suspend drop ;
|
||||
|
||||
: (spawn) ( thread -- )
|
||||
[
|
||||
|
|
@ -137,7 +143,7 @@ PRIVATE>
|
|||
>r { } set-datastack r>
|
||||
thread-quot [ call stop ] call-clear
|
||||
] 1 (throw)
|
||||
] suspend 2drop ;
|
||||
] "spawn" suspend 2drop ;
|
||||
|
||||
: spawn ( quot name -- thread )
|
||||
[
|
||||
|
|
@ -170,7 +176,7 @@ PRIVATE>
|
|||
<min-heap> 43 setenv
|
||||
initial-thread global
|
||||
[ drop f "Initial" [ die ] <thread> ] cache
|
||||
f over set-thread-continuation
|
||||
<box> over set-thread-continuation
|
||||
f over set-thread-registered?
|
||||
dup register-thread
|
||||
set-self ;
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ IN: concurrency.conditions
|
|||
: notify-all ( dlist -- )
|
||||
[ second resume ] dlist-slurp yield ;
|
||||
|
||||
: wait ( queue timeout -- )
|
||||
[ 2array swap push-front ] suspend 3drop ; inline
|
||||
: wait ( queue timeout status -- )
|
||||
>r [ 2array swap push-front ] r> suspend 3drop ; inline
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
! Copyright (C) 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel threads ;
|
||||
USING: kernel threads boxes ;
|
||||
IN: concurrency.exchangers
|
||||
|
||||
! Motivated by
|
||||
|
|
@ -9,18 +9,13 @@ IN: concurrency.exchangers
|
|||
TUPLE: exchanger thread object ;
|
||||
|
||||
: <exchanger> ( -- exchanger )
|
||||
f f 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 ;
|
||||
<box> <box> exchanger construct-boa ;
|
||||
|
||||
: exchange ( obj exchanger -- newobj )
|
||||
dup exchanger-thread [
|
||||
dup pop-object >r pop-thread resume-with r>
|
||||
dup exchanger-thread box-full? [
|
||||
dup exchanger-object box>
|
||||
>r exchanger-thread box> resume-with r>
|
||||
] [
|
||||
[ set-exchanger-object ] keep
|
||||
[ set-exchanger-thread ] curry suspend
|
||||
[ exchanger-object >box ] keep
|
||||
[ exchanger-thread >box ] curry "Exchange wait" suspend
|
||||
] if ;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ TUPLE: lock threads owner reentrant? ;
|
|||
|
||||
: acquire-lock ( lock timeout -- )
|
||||
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 ;
|
||||
|
||||
: release-lock ( lock -- )
|
||||
|
|
@ -54,7 +54,7 @@ TUPLE: rw-lock readers writers reader# writer ;
|
|||
|
||||
: acquire-read-lock ( lock timeout -- )
|
||||
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# ;
|
||||
|
||||
: notify-writer ( lock -- )
|
||||
|
|
@ -66,7 +66,7 @@ TUPLE: rw-lock readers writers reader# writer ;
|
|||
|
||||
: acquire-write-lock ( lock timeout -- )
|
||||
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 ;
|
||||
|
||||
: release-write-lock ( lock -- )
|
||||
|
|
|
|||
|
|
@ -73,18 +73,21 @@ MATCH-VARS: ?from ?to ?value ;
|
|||
SYMBOL: increment
|
||||
SYMBOL: decrement
|
||||
SYMBOL: value
|
||||
SYMBOL: exit
|
||||
|
||||
: counter ( value -- value )
|
||||
: counter ( value -- value ? )
|
||||
receive {
|
||||
{ { increment ?value } [ ?value + ] }
|
||||
{ { decrement ?value } [ ?value - ] }
|
||||
{ { value ?from } [ dup ?from send ] }
|
||||
{ { increment ?value } [ ?value + t ] }
|
||||
{ { decrement ?value } [ ?value - t ] }
|
||||
{ { value ?from } [ dup ?from send t ] }
|
||||
{ exit [ f ] }
|
||||
} match-cond ;
|
||||
|
||||
[ -5 ] [
|
||||
[ 0 [ t ] [ counter ] [ ] while ] "Counter" spawn
|
||||
{ increment 10 } over send
|
||||
{ decrement 15 } over send
|
||||
[ value , self , ] { } make swap send
|
||||
[ 0 [ counter ] [ ] [ ] while ] "Counter" spawn "counter" set
|
||||
{ increment 10 } "counter" get send
|
||||
{ decrement 15 } "counter" get send
|
||||
[ value , self , ] { } make "counter" get send
|
||||
receive
|
||||
exit "counter" get send
|
||||
] unit-test
|
||||
|
|
@ -26,12 +26,14 @@ TUPLE: mailbox threads data ;
|
|||
2over mailbox-data dlist-contains? [
|
||||
3drop
|
||||
] [
|
||||
2dup >r mailbox-threads r> wait block-unless-pred
|
||||
2dup >r mailbox-threads r> "mailbox" wait
|
||||
block-unless-pred
|
||||
] if ; inline
|
||||
|
||||
: block-if-empty ( mailbox timeout -- mailbox )
|
||||
over mailbox-empty? [
|
||||
2dup >r mailbox-threads r> wait block-if-empty
|
||||
2dup >r mailbox-threads r> "mailbox" wait
|
||||
block-if-empty
|
||||
] [
|
||||
drop
|
||||
] if ;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ TUPLE: semaphore count threads ;
|
|||
<dlist> semaphore construct-boa ;
|
||||
|
||||
: wait-to-acquire ( semaphore timeout -- )
|
||||
>r semaphore-threads r> wait ;
|
||||
>r semaphore-threads r> "semaphore" wait ;
|
||||
|
||||
: acquire ( semaphore timeout -- )
|
||||
dup semaphore-count zero? [
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ ARTICLE: "collections" "Collections"
|
|||
{ $subsection "hashtables" }
|
||||
{ $subsection "alists" }
|
||||
{ $heading "Other collections" }
|
||||
{ $subsection "boxes" }
|
||||
{ $subsection "dlists" }
|
||||
{ $subsection "heaps" }
|
||||
{ $subsection "graphs" }
|
||||
|
|
|
|||
|
|
@ -83,7 +83,10 @@ HOOK: run-process* io-backend ( desc -- handle )
|
|||
: wait-for-process ( process -- status )
|
||||
[
|
||||
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?
|
||||
[ "Process was killed" throw ] [ process-status ] if
|
||||
] with-timeout ;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: io.backend kernel continuations namespaces sequences
|
||||
assocs hashtables sorting arrays threads ;
|
||||
assocs hashtables sorting arrays threads boxes ;
|
||||
IN: io.monitors
|
||||
|
||||
<PRIVATE
|
||||
|
|
@ -35,24 +35,21 @@ M: monitor dispose
|
|||
TUPLE: simple-monitor handle callback ;
|
||||
|
||||
: <simple-monitor> ( handle -- simple-monitor )
|
||||
f (monitor) {
|
||||
f (monitor) <box> {
|
||||
set-simple-monitor-handle
|
||||
set-delegate
|
||||
set-simple-monitor-callback
|
||||
} simple-monitor construct ;
|
||||
|
||||
: construct-simple-monitor ( handle class -- simple-monitor )
|
||||
>r <simple-monitor> r> construct-delegate ; inline
|
||||
|
||||
: notify-callback ( simple-monitor -- )
|
||||
dup simple-monitor-callback
|
||||
f rot set-simple-monitor-callback
|
||||
[ resume ] when* ;
|
||||
simple-monitor-callback ?box [ resume ] [ drop ] if ;
|
||||
|
||||
M: simple-monitor fill-queue ( monitor -- )
|
||||
dup simple-monitor-callback [
|
||||
"Cannot wait for changes on the same file from multiple threads" throw
|
||||
] when
|
||||
[ swap set-simple-monitor-callback ] suspend drop
|
||||
[ swap simple-monitor-callback >box ]
|
||||
"monitor" suspend drop
|
||||
check-monitor ;
|
||||
|
||||
M: simple-monitor dispose ( monitor -- )
|
||||
|
|
|
|||
|
|
@ -3,10 +3,17 @@
|
|||
USING: io io.sockets io.files logging continuations kernel
|
||||
math math.parser namespaces parser sequences strings
|
||||
prettyprint debugger quotations calendar
|
||||
threads concurrency.combinators ;
|
||||
|
||||
threads concurrency.combinators assocs ;
|
||||
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
|
||||
|
||||
: with-client ( client quot -- )
|
||||
|
|
@ -15,23 +22,21 @@ LOG: accepted-connection NOTICE
|
|||
with-stream*
|
||||
] curry with-disposal ; inline
|
||||
|
||||
\ with-client NOTICE add-error-logging
|
||||
\ with-client DEBUG add-error-logging
|
||||
|
||||
: accept-loop ( server quot -- )
|
||||
[
|
||||
>r accept r> [ with-client ] 2curry
|
||||
"Client" spawn drop
|
||||
{ log-service servers } "Client" spawn-vars
|
||||
] 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
|
||||
|
||||
SYMBOL: servers
|
||||
\ server-loop NOTICE add-error-logging
|
||||
|
||||
: spawn-server ( addrspec quot -- )
|
||||
>r <server> dup servers get push r> server-loop ; inline
|
||||
|
||||
\ spawn-server NOTICE add-error-logging
|
||||
PRIVATE>
|
||||
|
||||
: local-server ( port -- seq )
|
||||
"localhost" swap t resolve-host ;
|
||||
|
|
@ -40,17 +45,18 @@ SYMBOL: servers
|
|||
f swap t resolve-host ;
|
||||
|
||||
: with-server ( seq service quot -- )
|
||||
[
|
||||
V{ } clone servers set
|
||||
[ spawn-server ] curry parallel-each
|
||||
] curry with-logging ; inline
|
||||
V{ } clone [
|
||||
servers [
|
||||
[ server-loop ] curry with-logging
|
||||
] with-variable
|
||||
] 3curry parallel-each ; inline
|
||||
|
||||
: stop-server ( -- )
|
||||
servers get [ dispose ] each ;
|
||||
|
||||
: received-datagram ( addrspec -- ) drop ;
|
||||
<PRIVATE
|
||||
|
||||
\ received-datagram NOTICE add-input-logging
|
||||
LOG: received-datagram NOTICE
|
||||
|
||||
: datagram-loop ( quot datagram -- )
|
||||
[
|
||||
|
|
@ -63,6 +69,8 @@ SYMBOL: servers
|
|||
|
||||
\ spawn-datagrams NOTICE add-input-logging
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: with-datagrams ( seq service quot -- )
|
||||
[
|
||||
[ swap spawn-datagrams ] curry parallel-each
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ M: mx register-io-task ( task mx -- )
|
|||
mx get-global register-io-task ;
|
||||
|
||||
: 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 -- )
|
||||
fd/container delete-at drop ;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ M: windows-nt-io add-completion ( handle -- )
|
|||
<io-callback> swap
|
||||
dup alien? [ "bad overlapped in save-callback" throw ] unless
|
||||
io-hash get-global set-at
|
||||
] suspend 3drop ;
|
||||
] "I/O" suspend 3drop ;
|
||||
|
||||
: wait-for-overlapped ( ms -- overlapped ? )
|
||||
>r master-completion-port get-global r> ! port ms
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
IN: tools.threads
|
||||
USING: threads kernel prettyprint prettyprint.config
|
||||
io io.styles sequences assocs namespaces sorting ;
|
||||
io io.styles sequences assocs namespaces sorting boxes ;
|
||||
|
||||
: thread. ( thread -- )
|
||||
dup thread-id 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. ( -- )
|
||||
standard-table-style [
|
||||
|
|
|
|||
|
|
@ -6,18 +6,27 @@ math.vectors models namespaces parser prettyprint quotations
|
|||
sequences sequences.lib strings threads listener
|
||||
tuples ui.commands ui.gadgets ui.gadgets.editors
|
||||
ui.gadgets.presentations ui.gadgets.worlds ui.gestures
|
||||
definitions ;
|
||||
definitions boxes ;
|
||||
IN: ui.tools.interactor
|
||||
|
||||
TUPLE: interactor
|
||||
history output
|
||||
thread quot busy?
|
||||
thread quot
|
||||
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 )
|
||||
use swap
|
||||
interactor-thread thread-continuation continuation-name
|
||||
assoc-stack ;
|
||||
dup interactor-busy? [ drop f ] [
|
||||
use swap
|
||||
interactor-continuation continuation-name
|
||||
assoc-stack
|
||||
] if ;
|
||||
|
||||
: init-caret-help ( interactor -- )
|
||||
dup editor-caret 100 <delay> swap set-interactor-help ;
|
||||
|
|
@ -29,13 +38,13 @@ help ;
|
|||
<source-editor>
|
||||
interactor construct-editor
|
||||
tuck set-interactor-output
|
||||
<box> over set-interactor-thread
|
||||
dup init-interactor-history
|
||||
dup init-caret-help ;
|
||||
|
||||
M: interactor graft*
|
||||
dup delegate graft*
|
||||
dup dup interactor-help add-connection
|
||||
f swap set-interactor-busy? ;
|
||||
dup interactor-help add-connection ;
|
||||
|
||||
: word-at-loc ( loc interactor -- word )
|
||||
over [
|
||||
|
|
@ -65,17 +74,16 @@ M: interactor model-changed
|
|||
over empty? [ 2drop ] [ interactor-history push-new ] if ;
|
||||
|
||||
: interactor-continue ( obj interactor -- )
|
||||
t over set-interactor-busy?
|
||||
interactor-thread resume-with ;
|
||||
interactor-thread box> resume-with ;
|
||||
|
||||
: clear-input ( interactor -- ) gadget-model clear-doc ;
|
||||
|
||||
: 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
|
||||
[ interactor-input. ] 2keep
|
||||
[ add-interactor-history ] keep
|
||||
[ clear-input ] curry in-thread ;
|
||||
[ clear-input ] curry "Clearing input" spawn drop ;
|
||||
|
||||
: interactor-eof ( interactor -- )
|
||||
dup interactor-busy? [
|
||||
|
|
@ -88,12 +96,7 @@ M: interactor model-changed
|
|||
] unless drop ;
|
||||
|
||||
: interactor-yield ( interactor -- obj )
|
||||
! dup gadget-graft-state first [
|
||||
f over set-interactor-busy?
|
||||
[ set-interactor-thread ] curry suspend ;
|
||||
! ] [
|
||||
! drop f
|
||||
! ] if ;
|
||||
[ interactor-thread >box ] curry "input" suspend ;
|
||||
|
||||
M: interactor stream-readln
|
||||
[ interactor-yield ] keep interactor-finish ?first ;
|
||||
|
|
@ -127,7 +130,7 @@ M: interactor stream-read-partial
|
|||
[
|
||||
drop parse-lines-interactive
|
||||
] [
|
||||
>r f swap set-interactor-busy? drop r>
|
||||
2nip
|
||||
dup delegate unexpected-eof? [ drop f ] when
|
||||
] recover ;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,7 @@ TUPLE: listener-gadget input output stack ;
|
|||
<scroller> "Input" <labelled-gadget> f track, ;
|
||||
|
||||
: welcome. ( -- )
|
||||
"If this is your first time with the Factor UI," 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
|
||||
"If this is your first time with Factor, please read the " print
|
||||
"cookbook" ($link) "." print nl ;
|
||||
|
||||
M: listener-gadget focusable-child*
|
||||
|
|
@ -45,7 +41,8 @@ M: listener-gadget tool-scroller
|
|||
listener-gadget-output find-scroller ;
|
||||
|
||||
: workspace-busy? ( workspace -- ? )
|
||||
workspace-listener listener-gadget-input interactor-busy? ;
|
||||
workspace-listener listener-gadget-input
|
||||
interactor-busy? ;
|
||||
|
||||
: get-listener ( -- listener )
|
||||
[ workspace-busy? not ] get-workspace* workspace-listener ;
|
||||
|
|
@ -81,8 +78,9 @@ M: listener-operation invoke-command ( target command -- )
|
|||
listener-gadget-input interactor-eof ;
|
||||
|
||||
: clear-output ( listener -- )
|
||||
[ listener-gadget-output [ pane-clear ] curry ] keep
|
||||
(call-listener) ;
|
||||
listener-gadget-output pane-clear ;
|
||||
|
||||
\ clear-output H{ { +listener+ t } } define-command
|
||||
|
||||
: clear-stack ( listener -- )
|
||||
[ clear ] swap (call-listener) ;
|
||||
|
|
@ -134,16 +132,16 @@ M: stack-display tool-scroller
|
|||
] with-stream* ;
|
||||
|
||||
: restart-listener ( listener -- )
|
||||
[ listener-thread ] curry "Listener" spawn drop ;
|
||||
dup com-end dup clear-output
|
||||
[ listener-thread ] curry
|
||||
"Listener" spawn drop ;
|
||||
|
||||
: init-listener ( listener -- )
|
||||
f <model> swap set-listener-gadget-stack ;
|
||||
|
||||
: <listener-gadget> ( -- gadget )
|
||||
listener-gadget construct-empty
|
||||
dup init-listener
|
||||
[ listener-output, listener-input, ] { 0 1 } build-track
|
||||
dup restart-listener ;
|
||||
listener-gadget construct-empty dup init-listener
|
||||
[ listener-output, listener-input, ] { 0 1 } build-track ;
|
||||
|
||||
: listener-help "ui-listener" help-window ;
|
||||
|
||||
|
|
@ -160,3 +158,11 @@ listener-gadget "toolbar" f {
|
|||
M: listener-gadget handle-gesture* ( gadget gesture delegate -- ? )
|
||||
3dup drop swap find-workspace workspace-page handle-gesture
|
||||
[ default-gesture-handler ] [ 3drop f ] if ;
|
||||
|
||||
M: listener-gadget graft*
|
||||
dup delegate graft*
|
||||
restart-listener ;
|
||||
|
||||
M: listener-gadget ungraft*
|
||||
dup com-end
|
||||
delegate ungraft* ;
|
||||
|
|
|
|||
|
|
@ -131,12 +131,10 @@ SYMBOL: ui-hook
|
|||
graft-queue [ notify ] dlist-slurp ;
|
||||
|
||||
: ui-step ( -- )
|
||||
[
|
||||
do-timers
|
||||
notify-queued
|
||||
layout-queued
|
||||
redraw-worlds
|
||||
] assert-depth ;
|
||||
[ do-timers ] assert-depth
|
||||
[ notify-queued ] assert-depth
|
||||
[ layout-queued "a" set ] assert-depth
|
||||
[ "a" get redraw-worlds ] assert-depth ;
|
||||
|
||||
: open-world-window ( world -- )
|
||||
dup pref-dim over set-gadget-dim dup relayout graft ui-step ;
|
||||
|
|
|
|||
Loading…
Reference in New Issue