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