I've got two futures that resolve to booleans. I basically want to do something like
(if (or @future1 @future2)
...)
but, with the optimization that whichever one finishes first, if it's true, then I don't wait for the remaining future to finish; just go. Of course if the value is false, then wait for the remaining future to finish. Is there a straightforward way of doing this?
In the general case, you can give the same promise to the two deliverers. E.g.:
(defn foo []
(let [p (promise)]
(future
(Thread/sleep (rand-int 1000))
(deliver p :a))
(future
(Thread/sleep (rand-int 1000))
(deliver p :b))
@p))
Calling (foo) will randomly yield :a or :b as soon as the first deliver occurs; the other deliver will be a no-op.
To your specific case, you're requiring two booleans be returned. The only thing I can think of (and it's a bit messy) would be to use a third promise shared between the deliverers:
(defn foo []
(let [a (promise)
b (promise)
link (promise)]
(future
(Thread/sleep (rand-int 5000))
(let [res (rand-nth [true false])]
(deliver link res)
(deliver a res)))
(future
(Thread/sleep (rand-int 5000))
(let [res (rand-nth [true false])]
(deliver link res)
(deliver b res)))
{:or (or @link @a @b)
:a? (realized? a)
:b? (realized? b)
:link @link
:a @a
:b @b}))
a delivers true first, the or completes immediately.a delivers false first, the @a returns immediately, then blocks on @b.b delivers true first, the or completes immediately.a delivers false first, it blocks on @a.Repeatedly invoke (foo) and you should see expected results, specifically, when :or is true, then sometimes :a? or :b? will be false, but both will always be true if :or is false.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With