I decided to start trying to understand crystal concurrency (in light of the preview_mt feature) and had a look at this: crystal-benchmarks/channel-primes.cr at master · bcardiff/crystal-benchmarks · GitHub
SIZE = ARGV.to_i def generate(chan) i = 2 loop do chan.send(i) i += 1 end end
I understand this. Takes a channel and just writes increasing numbers to it.
def filter(in_chan, out_chan, prime) loop do i = in_chan.receive if i % prime != 0 out_chan.send(i) end end end
I also understand this. Read from one channel and sends what it read out another channel when its divisible by “prime”.
ch = Channel(Int32).new spawn generate(ch)
Start fiber (or thread) with generator. Got that.
SIZE.times do prime = ch.receive puts prime ch1 = Channel(Int32).new spawn filter(ch, ch1, prime) ch = ch1 end
Now here I’m completely lost.
SIZE is the number of primes to compute. So, this spawns, let’s say, 15 fibers, who all read on the channel “ch” which is either the generated number or the output of the filter function?
Why is this not random? if we have multithreading, why do things still happen in a defined order?
The Filter function does this in a loop without end condition. Why does this even work, i.e. ever end?