Skip to content

Instantly share code, notes, and snippets.

@lnostdal
Last active November 7, 2018 12:30
Show Gist options
  • Select an option

  • Save lnostdal/3409086d436359888ade175311fe0a55 to your computer and use it in GitHub Desktop.

Select an option

Save lnostdal/3409086d436359888ade175311fe0a55 to your computer and use it in GitHub Desktop.
clojure.core.async: how to deal with deadlocks
;;; https://www.Quanto.ga
;; clojure.core.async: how to deal with deadlocks
;;
;; If you have a channel that in the "reader" or consumer also sends
;; to itself you might end up with a deadlock in certain cases. Especially
;; if you don't want to use buffered channels -- perhaps because it is
;; impossible to predict how much of a buffer you will need:
(let [ch (async/chan)
f (future
(dotimes [i 3]
(println "ch:" (async/<!! ch))
(async/>!! ch i))
(println "ch (last one): " (async/<!! ch)))]
(try
(async/>!! ch -1)
(Thread/sleep 500)
(finally
(future-cancel f)))
(println "...done"))
;; ch: -1
;; ...done
;; By using async/go or async/thread you can deal with this:
(let [ch (async/chan)
f (future
(dotimes [i 3]
(println "ch:" (async/<!! ch))
(async/go (async/>! ch i))) ;; or (async/thread (async/>!! ch i))
(println "ch (last one): " (async/<!! ch)))]
(try
(async/>!! ch -1)
(Thread/sleep 500)
(finally
(future-cancel f)))
(println "...done"))
;; ch: -1
;; ch: 0
;;ch: 1
;; ch (last one): 2
;;...done
;; Of course one could also use buffering in this case,
;; but this changes the properties of your system in a different way.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment