         [ set-promise-value ] keep
         [ t swap set-promise-fulfilled? ] keep
         [ promise-processes ] keep
-        0 <vector> swap set-promise-processes
-        [ schedule-thread ] each yield
+        V{ } clone swap set-promise-processes
+        [ thread-continuation schedule-thread ] each yield
     ] if ;
 
 <PRIVATE
- : (maybe-block-promise) ( promise -- promise )
+ : (maybe-block-promise) ( promise timeout -- promise )
     #! Block the process if the promise is unfulfilled. This is different from
     #! (mailbox-block-if-empty) in that when a promise is fulfilled, all threads
     #! need to be resumed, rather than just one.
-    dup promise-fulfilled? [
-        [ swap promise-processes push stop ] callcc0
-    ] unless ;
-PRIVATE>
+    over promise-fulfilled? [
+        drop
+    ] [
+        [ <thread> swap promise-processes push stop ] callcc0
+        drop
+    ] if ;
+PRIVATE>
+
+: ?promise* ( promise timeout -- result )
+    (maybe-block-promise) promise-value ;
 
 : ?promise ( promise -- result )
-    (maybe-block-promise) promise-value ;
+    f ?promise* ;
 
 ! ******************************
 ! Experimental code below

<PRIVATE
: tag-message ( message -- tagged-message )
    #! Given a message, wrap it with the sending process and a unique tag.
    >r self random-64 r> 3array ;
PRIVATE>

: send-synchronous ( message process -- reply )


: mailbox-put ( obj mailbox -- )
    [ mailbox-data dlist-push-end ] keep
    [ mailbox-threads ] keep
    V{ } clone swap set-mailbox-threads
    [ thread-continuation schedule-thread ] each yield ;

<PRIVATE
: (mailbox-block-unless-pred) ( pred mailbox timeout -- )
    2over mailbox-data dlist-contains? [
        3drop
    ] [
        [ <thread> swap mailbox-threads push stop ] callcc0
        (mailbox-block-unless-pred)
    ] if ; inline

: (mailbox-block-if-empty) ( mailbox timeout -- mailbox2 )
    over mailbox-empty? [
        [ <thread> swap mailbox-threads push stop ] callcc0
        "(mailbox-block-if-empty)" print flush
        (mailbox-block-if-empty)
    ] [
        drop
    ] if ;
PRIVATE>
: mailbox-get* ( mailbox timeout -- obj )
    (mailbox-block-if-empty)
    mailbox-data dlist-pop-front ;

: mailbox-get ( mailbox -- obj )
    f mailbox-get* ;

: mailbox-get-all* ( mailbox timeout -- array )
    (mailbox-block-if-empty)
    [ dup mailbox-empty? ]
    [ dup mailbox-data dlist-pop-front ]
    { } unfold ;

: mailbox-get-all ( mailbox -- array )
    f mailbox-get-all* ;

: while-mailbox-empty ( mailbox quot -- )
    over mailbox-empty? [
        dup >r swap slip r> while-mailbox-empty
