niic
niic

Reputation: 83

Create channels that need to be closed several times

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

Answers (2)

leetwinski
leetwinski

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

OlegTheCat
OlegTheCat

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

Related Questions