(mult ch)
Creates and returns a mult(iple) of the supplied channel. Channels containing copies of the channel can be created with 'tap', and detached with 'untap'. Each item is distributed to all taps in parallel and synchronously, i.e. each tap must accept before the next item is distributed. Use buffering/windowing to prevent slow taps from holding up the mult. Items received when there are no taps get dropped. If a tap puts to a closed channel, it will be removed from the mult.
user=> (def sz 20)
#'user/sz
user=> (def c (chan sz))
#'user/c
user=> (def mult-c (mult c))
#'user/mult-c
user=> (def cx (chan sz))
#'user/cx
user=> (def cy (chan sz))
#'user/cy
user=> (def cz (chan sz))
#'user/cz
user=> (tap mult-c cx)
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@63942268>
user=> (tap mult-c cy)
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@1f025346>
user=> (tap mult-c cz)
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@29d4cd91>
user=> (put! c "sent to all")
true
user=> (<!! cx)
"sent to all"
user=> (<!! cy)
"sent to all"
user=> (<!! cz)
"sent to all"
;; Dont read from the source of mult, or you'll get read race contention
user> (def a (chan))
user> (def m (mult a))
user> (def b (chan))
user> (tap m b)
user> (go-loop [] (when-let [v (<! b)] (do (println "b got" v) (recur))))
;; next line is pain self inflicted
user> (go-loop [] (when-let [v (<! a)] (do (println "a(source) got" v) (recur))))
user> (put! a "Hello ")
b got Hello
user> (put! a " World")
a(source) got World