Fork me on GitHub

What's the reason for the seeming impossibility of having a rendezvous backed by a transducer? I'd like to use transducers for implementing some sort of message validator. It would be problematic if the validation ran for channels of buffer size 1, 2, 3, ... but not 0

Alex Miller (Clojure team)04:01:09

transducers can be expanding and create new intermediate elements. those have to go somewhere so a buffer is required.


:thumbsup: I see! In a buffered chan, what happens when a transducer creates intermediate elements beyond the buffer's capacity? Does execution simply park, cleanly?

Alex Miller (Clojure team)04:01:39

no, it overfills the buffer


would that cause an exception?

Alex Miller (Clojure team)04:01:10

no, it expands to hold the extras

👍 4

I wonder about the behavior in this case. It will keep expanding even if the buffer is already larger than the original size. Pending puts will be executed upon a matching take, without checking whether the buffer is full according to original size. It just assumes that the new take operation releases space in the buffer. If every put is expanding, the buffer will expand indefinitely.

Alex Miller (Clojure team)14:01:10

yes, so be careful about using expanding transducers (cat / mapcat are the only ones in core) in async channels


Hi everyone! n00b question: why does the following block forever, and not return [nil c] after c is close!d?

(let [c (chan)]
    (Thread/sleep 200)
    (close! c))
  (alts!! [c]))


My guess would be you've been playing around with core.async stuff for a while without restarting your repl, and as part of that playing around bat some point you did something that blocked up the threadpool go blocks run on


That is very likely. Checking...


Indeed! Thanks @hiredman!


In general you also should not use thread sleep in go blocks, you should use a timeout channel


Sure. That was just to simplify an example


But this begs the question: is there some way that I can check for (and clear?) orphaned go routines, while I'm screwing around in the repl?

Alex Miller (Clojure team)20:01:38

doing a thread dump will reveal that all the go threads are blocked (re detection), but no way to "clear" that


"thread dump"? I'm not seeing anything relevant in my first few searches

Alex Miller (Clojure team)20:01:45

if you're on unix/mac, just do ctrl-\

Alex Miller (Clojure team)20:01:52

or on windows ctrl-break


#TIL, thanks!

Alex Miller (Clojure team)20:01:38

the threads are named async-dispatch-[1-8]

Alex Miller (Clojure team)20:01:31

a thread able to be used is probably marked "WAITING (parking)"

Alex Miller (Clojure team)20:01:32

if it's in a Thread/sleep, it will say "TIMED_WAITING (sleeping)". if it's blocked for some other reason, you may see other stuff


I was just about to ask 😉


It is tricky, core.async doesn't really provide that, and the jvm just understands threads, so bridging that is tough

Alex Miller (Clojure team)20:01:51

the key is no blocking ops in go blocks - obviously Thread/sleep does that (you can actually Thread/interrupt that), and i/o stuff. there is a new system property you can use to fail if a core.async blocking op is done in go blocks

💯 8

Thanks for this. Where can I learn more on how to fail when there is blocking op is used in a go block?


Yeah, my actual implementation is CPU-bound. I was just using the Thread/sleep to test the hypothesis that alts!! won't "see" the closing of the channel, if done after alts!! started blocking on the channel.


Takes will see the channel closing, but pending puts will not and will block forever.