2008-02-18 06:07:40 -05:00
|
|
|
! Copyright (C) 2005, 2008 Chris Double, Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
|
|
!
|
|
|
|
! Concurrency library for Factor based on Erlang/Termite style
|
|
|
|
! concurrency.
|
|
|
|
IN: concurrency.messaging
|
2008-02-18 08:30:16 -05:00
|
|
|
USING: dlists threads sequences continuations
|
2008-02-18 06:07:40 -05:00
|
|
|
namespaces random math quotations words kernel arrays assocs
|
2008-02-18 10:08:59 -05:00
|
|
|
init system concurrency.conditions ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
TUPLE: mailbox threads data ;
|
|
|
|
|
|
|
|
: <mailbox> ( -- mailbox )
|
2008-02-18 08:30:16 -05:00
|
|
|
<dlist> <dlist> \ mailbox construct-boa ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: mailbox-empty? ( mailbox -- bool )
|
|
|
|
mailbox-data dlist-empty? ;
|
|
|
|
|
|
|
|
: mailbox-put ( obj mailbox -- )
|
|
|
|
[ mailbox-data push-front ] keep
|
|
|
|
mailbox-threads notify-all ;
|
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
: block-unless-pred ( pred mailbox timeout -- )
|
|
|
|
2over mailbox-data dlist-contains? [
|
|
|
|
3drop
|
|
|
|
] [
|
2008-02-19 15:38:02 -05:00
|
|
|
2dup >r mailbox-threads r> "mailbox" wait
|
|
|
|
block-unless-pred
|
2008-02-18 06:07:40 -05:00
|
|
|
] if ; inline
|
|
|
|
|
|
|
|
: block-if-empty ( mailbox timeout -- mailbox )
|
|
|
|
over mailbox-empty? [
|
2008-02-19 15:38:02 -05:00
|
|
|
2dup >r mailbox-threads r> "mailbox" wait
|
|
|
|
block-if-empty
|
2008-02-18 06:07:40 -05:00
|
|
|
] [
|
|
|
|
drop
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
|
|
|
: mailbox-peek ( mailbox -- obj )
|
2008-02-18 17:20:18 -05:00
|
|
|
mailbox-data peek-back ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: mailbox-get-timeout ( mailbox timeout -- obj )
|
2008-02-18 17:20:18 -05:00
|
|
|
block-if-empty mailbox-data pop-back ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: mailbox-get ( mailbox -- obj )
|
2008-02-18 08:30:16 -05:00
|
|
|
f mailbox-get-timeout ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: mailbox-get-all-timeout ( mailbox timeout -- array )
|
2008-02-18 08:30:16 -05:00
|
|
|
block-if-empty
|
2008-02-18 06:07:40 -05:00
|
|
|
[ dup mailbox-empty? ]
|
|
|
|
[ dup mailbox-data pop-back ]
|
|
|
|
[ ] unfold nip ;
|
|
|
|
|
|
|
|
: mailbox-get-all ( mailbox -- array )
|
2008-02-18 08:30:16 -05:00
|
|
|
f mailbox-get-all-timeout ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: while-mailbox-empty ( mailbox quot -- )
|
|
|
|
over mailbox-empty? [
|
|
|
|
dup >r swap slip r> while-mailbox-empty
|
|
|
|
] [
|
|
|
|
2drop
|
|
|
|
] if ; inline
|
|
|
|
|
|
|
|
: mailbox-timeout-get? ( pred mailbox timeout -- obj )
|
2008-02-18 08:30:16 -05:00
|
|
|
[ block-unless-pred ] 3keep drop
|
2008-02-18 06:07:40 -05:00
|
|
|
mailbox-data delete-node-if ; inline
|
|
|
|
|
|
|
|
: mailbox-get? ( pred mailbox -- obj )
|
2008-02-18 17:20:18 -05:00
|
|
|
f mailbox-timeout-get? ; inline
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
TUPLE: linked error thread ;
|
|
|
|
|
2008-02-18 17:20:18 -05:00
|
|
|
C: <linked> linked
|
2008-02-18 06:07:40 -05:00
|
|
|
|
2008-02-18 17:20:18 -05:00
|
|
|
GENERIC: send ( message process -- )
|
2008-02-18 06:07:40 -05:00
|
|
|
|
2008-02-18 08:30:16 -05:00
|
|
|
: mailbox-of ( thread -- mailbox )
|
|
|
|
dup thread-mailbox [ ] [
|
|
|
|
<mailbox> dup rot set-thread-mailbox
|
|
|
|
] ?if ;
|
|
|
|
|
2008-02-18 06:07:40 -05:00
|
|
|
M: thread send ( message thread -- )
|
2008-02-18 08:30:16 -05:00
|
|
|
mailbox-of mailbox-put ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: ?linked dup linked? [ rethrow ] when ;
|
|
|
|
|
2008-02-18 08:30:16 -05:00
|
|
|
: mailbox self mailbox-of ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: receive ( -- message )
|
|
|
|
mailbox mailbox-get ?linked ;
|
|
|
|
|
|
|
|
: receive-if ( pred -- message )
|
|
|
|
mailbox mailbox-get? ?linked ; inline
|
|
|
|
|
2008-02-18 17:20:18 -05:00
|
|
|
: rethrow-linked ( error process supervisor -- )
|
2008-02-18 06:07:40 -05:00
|
|
|
>r <linked> r> send ;
|
|
|
|
|
2008-02-18 10:08:59 -05:00
|
|
|
: spawn-linked-to ( quot name mailbox -- thread )
|
|
|
|
[ >r <linked> r> mailbox-put ] curry <thread>
|
|
|
|
[ (spawn) ] keep ;
|
|
|
|
|
2008-02-18 06:07:40 -05:00
|
|
|
: spawn-linked ( quot name -- thread )
|
2008-02-18 10:08:59 -05:00
|
|
|
mailbox spawn-linked-to ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
TUPLE: synchronous data sender tag ;
|
|
|
|
|
|
|
|
: <synchronous> ( data -- sync )
|
|
|
|
self random-256 synchronous construct-boa ;
|
|
|
|
|
|
|
|
TUPLE: reply data tag ;
|
|
|
|
|
|
|
|
: <reply> ( data synchronous -- reply )
|
|
|
|
synchronous-tag \ reply construct-boa ;
|
|
|
|
|
|
|
|
: send-synchronous ( message thread -- reply )
|
2008-02-18 17:20:18 -05:00
|
|
|
>r <synchronous> dup r> send [
|
|
|
|
over reply? [
|
|
|
|
>r reply-tag r> synchronous-tag =
|
|
|
|
] [
|
|
|
|
2drop f
|
|
|
|
] if
|
|
|
|
] curry receive-if reply-data ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: reply-synchronous ( message synchronous -- )
|
2008-02-18 08:30:16 -05:00
|
|
|
[ <reply> ] keep synchronous-sender send ;
|
2008-02-18 10:08:59 -05:00
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
: remote-processes ( -- hash )
|
|
|
|
\ remote-processes get-global ;
|
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
|
|
|
: register-process ( name process -- )
|
|
|
|
swap remote-processes set-at ;
|
|
|
|
|
|
|
|
: unregister-process ( name -- )
|
|
|
|
remote-processes delete-at ;
|
|
|
|
|
|
|
|
: get-process ( name -- process )
|
|
|
|
dup remote-processes at [ ] [ thread ] ?if ;
|
|
|
|
|
|
|
|
\ remote-processes global [ H{ } assoc-like ] change-at
|