1 ! Copyright (C) 2005, 2010 Chris Double, Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors concurrency.conditions continuations deques
4 destructors dlists fry kernel locals sequences threads
6 IN: concurrency.mailboxes
8 TUPLE: mailbox { threads dlist } { data dlist } ;
10 : <mailbox> ( -- mailbox )
13 <dlist> >>data ; inline
15 : mailbox-empty? ( mailbox -- bool )
16 data>> deque-empty? ; inline
18 GENERIC: mailbox-put ( obj mailbox -- )
20 M: mailbox mailbox-put
22 [ threads>> notify-all ] bi yield ;
24 : wait-for-mailbox ( mailbox timeout -- )
25 [ threads>> ] dip "mailbox" wait ; inline
27 :: block-unless-pred ( ... mailbox timeout pred: ( ... message -- ... ? ) -- ... )
28 mailbox data>> pred dlist-any? [
29 mailbox timeout wait-for-mailbox
30 mailbox timeout pred block-unless-pred
31 ] unless ; inline recursive
33 : block-if-empty ( mailbox timeout -- mailbox )
35 2dup wait-for-mailbox block-if-empty
38 ] if ; inline recursive
40 : mailbox-peek ( mailbox -- obj )
43 GENERIC#: mailbox-get-timeout 1 ( mailbox timeout -- obj )
45 M: mailbox mailbox-get-timeout block-if-empty data>> pop-back ;
47 : mailbox-get ( mailbox -- obj )
48 f mailbox-get-timeout ; inline
50 : mailbox-get-all-timeout ( mailbox timeout -- seq )
51 block-if-empty data>> [ ] collector [ slurp-deque ] dip ;
53 : mailbox-get-all ( mailbox -- seq )
54 f mailbox-get-all-timeout ;
56 : while-mailbox-empty ( mailbox quot -- )
57 [ '[ _ mailbox-empty? ] ] dip while ; inline
59 : mailbox-get-timeout? ( mailbox timeout pred -- obj )
61 [ [ drop data>> ] dip delete-node-if ]
64 : mailbox-get? ( mailbox pred -- obj )
65 f swap mailbox-get-timeout? ; inline
67 : wait-for-close-timeout ( mailbox timeout -- )
69 _ 2dup wait-for-mailbox wait-for-close-timeout
72 : wait-for-close ( mailbox -- )
73 f wait-for-close-timeout ;
75 TUPLE: linked-error error thread ;
77 C: <linked-error> linked-error
79 : ?linked ( message -- message )
80 dup linked-error? [ rethrow ] when ;
82 TUPLE: linked-thread < thread supervisor ;
84 M: linked-thread error-in-thread
85 [ <linked-error> ] [ supervisor>> ] bi mailbox-put stop ;
87 : <linked-thread> ( quot name mailbox -- thread' )
88 [ linked-thread new-thread ] dip >>supervisor ;
90 : spawn-linked-to ( quot name mailbox -- thread )
91 <linked-thread> [ (spawn) ] keep ;
93 { "concurrency.mailboxes" "debugger" } "concurrency.mailboxes.debugger" require-when