Fork me on GitHub
#core-async
<
2018-03-14
>
synthomat14:03:10

Hey I’ve got a small question concerning threads. I have a producer and consumer. Unfortunatelly I can’t find anything like Thread.join from java to wait until all threads quit. Probably I just misunderstood the concept of core/async

synthomat14:03:08

How to wait for multiple channels to complete before the application quits?

synthomat14:03:24

apparently it help to create a dummy thread looping infinitely to keep channels running. Doesn’t feel right, though

bjr14:03:18

You can block on all the channels in the primary thread. (run! async/<!! <coll-of-core.async-threads>)

synthomat15:03:28

wow interesting, works indeed

synthomat15:03:32

thanks alot!

synthomat15:03:54

Not sure I understood. Why is the application blocking at this point? eventhough there might be a message comming to the channel?

bjr15:03:48

I’m not sure what you’re trying to do. <!! is a blocking take from a channel. That’ll block until either a message is put on the channel or the channel is closed.

bjr15:03:18

Would you mind providing a bit more context?

synthomat15:03:35

For the testing scenario I created a go-loop that listens to the same channel; last command in the app is <!! channel and before that I send a message in a separate thread. The go loop prints out the message but the program does not quit. Why doesn’t it quit although there was a message and the blocking read should have passed? Because the go-loop picked the message before the last (<!! channel) ?

synthomat15:03:45

ok for the context

synthomat15:03:27

I have a $something-preprocessing loop, that processes data and sends a message on a channel. this message shall be processed in another thread. The pre-processing runs much faster than the actual processing

synthomat15:03:03

I thought core.async might be the right tool for that. Otherwise I would have realized this with ordinary java threads…

bjr15:03:59

Is the go-loop infinitely recursing?

bjr15:03:22

And you’re blocking on the channel returned by go-loop?

synthomat15:03:02

(def inbound (chan 10))

(go-loop []
  (let [msg (<! inbound)]
    (when msg
      (println "Channel:" msg)))
  (recur))

(future (Thread/sleep 1000) (>!! inbound "Some message"))
(<!! inbound)

(println "I am never called…")

; Channel: Some message

synthomat15:03:18

This actually works as intended, but I do not understand why…

bjr15:03:51

So you want "I am never called.." to be printed?

bjr15:03:04

and the process to then exit?

bjr15:03:30

sorry about all the questions..just trying to make sure I understand

bjr15:03:20

in that snippet only 1 message is put to inbound but there are 2 takes

bjr15:03:27

The second take will never complete because it’s waiting for a second put.

synthomat15:03:53

Like i said it’s being printed. Just as expected. I just don’t undestand, why the application blocks at (<!! inbound)

synthomat15:03:10

So for my understanding the go-loop gets the message first, so that the “message queue” is emptied before (<!! inbound) can pick it up?

synthomat15:03:42

is there a chance that the go-loop misses the message? Or is the order of consumption already defined the order of consumers in the code?

synthomat15:03:40

(also: fighting with english 😅)

synthomat15:03:53

nevermind, I’ll experiment with the code a bit. it might help

synthomat15:03:00

thanks so far 🙂

bjr16:03:24

I do think the ordering there is indeterminate. The body of the future may technically be able to execute before the body of the go-loop.

bjr16:03:11

Though that Thread/sleep of 1000ms blows out that window.

bjr16:03:41

In tests where ordering is important I do often use java threads or latches directly to ensure code is executed in a particular order.