Рассмотрим следующий фрагмент кода, взятый из пример обхода core.async а>:
(let [c1 (chan)
c2 (chan)]
(thread
(while true
(let [[v ch] (alts!! [c1 c2])]
(println "Read" v "from" ch))))
(>!! c1 "hi")
(>!! c2 "there"))
Я предполагаю, что поток имеет ссылку на оба канала c1
и c2
и в основном будет работать вечно, пытаясь получить значения из любого из них, которые никогда не поступят. Таким образом, ни каналы не будут собирать мусор, ни поток не завершится. Даже если мы явно close!
каналов, поток все равно будет продолжаться. Верен ли мой вывод или я что-то упускаю?
Я спрашиваю, потому что пытаюсь найти способ успешно протестировать такой код core.async с таким бесконечно работающим потребителем. Моя текущая попытка выглядит так:
(let [c1 (chan)
c2 (chan)]
(go
(>!! c1 "hi")
(>!! c2 "there"))
(async/thread
(loop [[v ch] (alts!! [c1 c2])]
(println "Read" v "from" ch)
(when-let [[nv nch] (alts!! [c1 c2])]
(if nv
(recur [nv nch])
:done)))))
Это возвращает канал результата (из thread
), для которого я хотел бы заблокировать значение :done
, но мне нужен способ закрытия (по крайней мере одного из) каналов. Я мог бы вернуть список двух каналов c1, c2
и канал результата, возвращенный thread
, а затем close!
, например. c1
после этого и проверьте канал результата, но это очень уродливо:
(let [c1 (chan)
c2 (chan)]
(go
(>!! c1 "hi")
(>!! c2 "there"))
[c1 c2 (async/thread
(loop [[v ch] (alts!! [c1 c2])]
(println "Read" v "from" ch)
(when-let [[nv nch] (alts!! [c1 c2])]
(if nv
(recur [nv nch])
:done))))])
=> [#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@60eb5def> #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@7c64279e> #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@136535df>]
Read hi from #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@60eb5def>
Read there from #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@7c64279e>
(let [[c1 c2 resultchan] *1]
(close! c1)
(<!! resultchan))
=>:done
В качестве альтернативы я мог бы, вероятно, отправить специальное значение «Конец связи», которое я мог бы затем проверить на принимающей стороне.
Как выглядит наилучшая практика для этого?
go
разрешены оба варианта. Кроме того, для проблемы, которую я пытаюсь решить, не имеет значения, использую ли я>!!
или>!
. - person schaueho   schedule 24.06.2015