Неспособность закрыть канал вызывает бессрочную блокировку
Вот пример с http://www.braveclojure.com/core-async/:
(defn hotdog-machine-v2 [hotdog-count]
(let [in (chan) out (chan)]
(go (loop [hc hotdog-count]
(if (> hc 0)
(let [input (<! in)]
(if (= 3 input)
(do
(>! out "hotdog")
(recur (dec hc)) )
(do
(>! out (Exception. "Not enough payment!"))
(recur hc))))
(do
(close! in)
(close! out)))))
[in out]))
(let [[in out] (hotdog-machine-v2 2)]
(>!! in "pocket lint")
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
)
Если я пропускаю часть, закрывающую канал, то этот код зависает навсегда, почему?
1 ответ
Если я запускаю это в обычном случае с закрытием, он печатает это:
user> (let [[in out] (hotdog-machine-v2 2)]
(>!! in "pocket lint")
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out)))
#error {
:cause Not enough payment!
:via
[{:type java.lang.Exception
:message Not enough payment!
... stack trace here ...
[java.lang.Thread run Thread.java 724]]}
hotdog
hotdog
nil ;; <---- look here
Последнее nil является результатом последнего чтения из out чтения значения nil, которое отправляется в результате закрытия канала, потому что на машине нет горячих собак. Без того последнего закрытия (>!! in 3)
блоки в ожидании чего-то, чтобы прочитать из чана, что никто не собирается делать. По умолчанию запись в core.async chans не удается записать, пока кто-то не готов прочитать это значение
Если я вынимаю close и вынимаю последнюю запись, она не печатает этот ноль и не блокирует:
user> (let [[in out] (hotdog-machine-v2 2)]
(>!! in "pocket lint")
(println (<!! out))
(>!! in 3)
(println (<!! out))
(>!! in 3)
(println (<!! out))
)
#error {
:cause Not enough payment!
:via
[{:type java.lang.Exception
:message Not enough payment!
:at ... stack trace here ...}
hotdog
hotdog