Reputation: 83
My situation is that the same channel is shared between different functions and I need to close the channel when all of this functions signal they are done with it. This is what I've come up with but it's not ideal because I need to handle tow channels and need to send a special keyword instead of using the close! function. Is there another, better way to do this? Is there some feature of core.async to do this?
(defn shared-chan [n]
(let [in (chan)
out (chan)]
(go-loop [n n]
(if (= n 0)
(do
(async/close! in)
(async/close! out))
(let [in-msg (<! in)]
(if (not= :close in-msg)
(do
(>! out in-msg)
(recur n))
(recur (dec n))))))
[in out]))
Upvotes: 2
Views: 105
Reputation: 17859
you can generate this shared channel using take
transducer. For example if you want an auto closable channel for 3 items:
user> (require '[clojure.core.async :as a])
nil
user> (def shared-ch (a/chan 3 (take 3)))
#'user/shared-ch
user> (a/go-loop []
(when-let [val (a/<! shared-ch)]
(println :reading val)
(recur)))
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x6bb1dee5 "clojure.core.async.impl.channels.ManyToManyChannel@6bb1dee5"]
user> (a/>!! shared-ch 1)
true:reading 1
user> (a/>!! shared-ch 2)
true:reading 2
user> (a/>!! shared-ch 3)
true:reading 3
user> (a/>!! shared-ch 4)
false
user> (a/>!! shared-ch 5)
false
you can see, that the channel has been closed as soon as the transducer has exhausted (as false
is returned after the writing attempt)
Upvotes: 0
Reputation: 4513
merge
may help you. According to the doc, merge
Takes a collection of source channels and returns a channel which contains all values taken from them. ... The channel will close after all the source channels have closed.
So, basically you need to create a channel for each of your functions and then merge
them into one.
Upvotes: 2