Fork me on GitHub
#core-async
<
2020-06-12
>
pmooser18:06:00

It's a little shocking to find out that timeout will reuse the same channels. I understand why, but it's not like it's even easy to figure out that is what's being done, since printing doesn't print different timeouts distinctly or anything. It's the kind of thing that when you discover it, it's probably because it exploded in your face.

pmooser18:06:46

I think it would be great if at the very least, the doc string made this clear.

Alex Miller (Clojure team)18:06:42

there is a ticket for this

Alex Miller (Clojure team)18:06:53

have not gotten around to doing it

dominicm18:06:40

What's the bug?

Alex Miller (Clojure team)18:06:43

partially because I'm torn between whether it's something that should be better doc'ed or made more defensive in the code

Alex Miller (Clojure team)18:06:53

if you close a timeout channel you close all timeout channels

Alex Miller (Clojure team)18:06:01

that's the blowing up part :)

hiredman19:06:22

I've accidentally done things like used timeouts as keys in maps

dominicm19:06:55

Ah, I see. Phew. I was worried they were reused in a different context.

pmooser19:06:30

@alexmiller For me, the problem wasn't that it was blowing up, but I erroneously assumed they would be unique, so I built some maps based on that assumption and was terribly surprised. But if it were documented, that would have at least saved me from myself!

pmooser19:06:53

And because they don't print distinctly, it's not that easy to figure out what is going on.

pmooser19:06:15

Until I read the source code ... which is not the ideal way to understand what is happening.

pmooser22:06:06

It occurs to me that a dumb workaround would be:

(defn dumb-timeout
  [ms]
  (go
    (<! (timeout ms))))

noisesmith22:06:05

or (pipe (timeout ms) (chan) false)

noisesmith22:06:26

that's likely less complex under the hood than a go block(?)

noisesmith22:06:50

nope, just expands to a go-loop

raspasov23:06:24

@pmooser so is the issue that the (timeout) channels close “at the same time” every 10 ms?

raspasov23:06:22

@alexmiller what do you mean by “if you close a timeout channel you close all timeout channels” ?

raspasov23:06:05

(do
  (clojure.core.async/go
    (let [t1 (clojure.core.async/timeout 10000)]
      (clojure.core.async/<! t1)
      (println (str "t1::: " t1))))

  (clojure.core.async/go
    (let [t2 (clojure.core.async/timeout 10000)]
      (clojure.core.async/close! t2)
      (println (str "t2::: " t2)))))
this outputs: (immediately) t2::: clojure.core.async.impl.channels.ManyToManyChannel@522c88e6 (wait ~10 seconds) t1::: clojure.core.async.impl.channels.ManyToManyChannel@8ea59ed

raspasov23:06:17

For a moment I got scared 🙂

raspasov23:06:31

I thought that it “globally” closes all timeout channels…