Thursday, June 7, 2018

clojure.core.async: how to deal with deadlocks

Perhaps I should post some code snippets and tips on this blog? Much of this will probably be obvious and simple, but it's stuff I sometimes forget.

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.

No comments:

Post a Comment