Skip to content

Instantly share code, notes, and snippets.

@michalmarczyk
Created July 12, 2013 21:50
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save michalmarczyk/5988137 to your computer and use it in GitHub Desktop.
Short-circuiting logical conjunction of several futures' results in core.async
(defn thread-and
"Call each of the fs on a separate thread. Return logical
conjunction of the results. Short-circuit (and cancel the calls
to remaining fs) on first falsey value returned."
[& fs]
(let [futs-and-cs
(doall (for [f fs]
(let [c (chan)]
[(future (>!! c (f))) c])))]
(loop [futs-and-cs futs-and-cs]
(if (seq futs-and-cs)
(let [[result c] (alts!! (map peek futs-and-cs))]
(if result
(recur (remove #(identical? (peek %) c)
futs-and-cs))
(do (doseq [fut (map first futs-and-cs)]
(future-cancel fut))
false)))
true))))
(comment
(thread-and (constantly true) (constantly true))
;;= true
(thread-and (constantly true) (constantly false))
;;= false
;; prints :foo before returning false
(thread-and #(do (Thread/sleep 3000) false)
#(do (Thread/sleep 1000) (println :foo)))
;; does not print :foo
(thread-and #(do (Thread/sleep 3000) false)
#(do (Thread/sleep 7000) (println :foo)))
)
@michalmarczyk
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment