Неспособность закрыть канал вызывает бессрочную блокировку

Вот пример с 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
Другие вопросы по тегам