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
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?
no, it overfills the buffer
would that cause an exception?
no, it expands to hold the extras
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.
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)]
(go
(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?
doing a thread dump will reveal that all the go threads are blocked (re detection), but no way to "clear" that
It is tricky, core.async doesn't really provide that, and the jvm just understands threads, so bridging that is tough
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
Thanks for this. Where can I learn more on how to fail when there is blocking op is used in a go block?
"thread dump"? I'm not seeing anything relevant in my first few searches
if you're on unix/mac, just do ctrl-\
or on windows ctrl-break
#TIL, thanks!
the threads are named async-dispatch-[1-8]
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.
a thread able to be used is probably marked "WAITING (parking)"
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 😉
yeah, I assumed
Thanks for the help, @hiredman @alexmiller!