Fork me on GitHub
#core-async
<
2024-03-07
>
adamfrey15:03:44

Could I get help understanding some behavior of core.async? I may be introducing a race condition. I'm using the latest version: 1.6.681 Here is my code testing a/mult and a/tap

(defn mult-test
  [input]
  (let [buffer-size  (count input)
        source-items (doto (a/chan buffer-size)
                       (a/onto-chan! input))
        mult-source  (a/mult source-items)
        a-items      (a/chan buffer-size (map (fn [i]
                                                (println "a ITEM" i)
                                                {:a i})))
        b-items      (a/chan buffer-size (map (fn [i]
                                                (println "b ITEM" i)
                                                {:b i})))]
    (a/tap mult-source a-items)
    (a/tap mult-source b-items)
    (println "=======================")
    (println "got: " (first (a/alts!! [a-items b-items])))))

(mult-test (range 5))
Calling (mult-test (range 5)) from my REPL usually prints what I would expect
=======================
a ITEM 0
got:  b ITEM 0
{:a 0}
a ITEM 1
b ITEM 1
...
but sometimes it prints only the following and hangs indefinitely.
=======================
I know that the a/alts!! call is blocking, but I thought that by calling the a/tap calls immediately prior, the a-items and b-items channels should start filling up in the background even if my main thread is blocking

hiredman16:03:37

Mult runs a go loop that copies the input to the output, and you are racing that go loop

adamfrey16:03:06

Thank you. To make sure I understand: would I be in a better place if I move my a/onto-chan! until after the a/taps have already been set up?

adamfrey16:03:07

awesome, thanks so much