Is sleep in Crystal fiber expected to block?

I am trying to learn Crystal, hoping to use it instead of Go. I am currently using Crystal version 0.27.2. I tried this simple code to experiment with concurrent programming:

chan = Channel(String).new
5.times do |i|
    spawn do
        sleep 5-i
        chan.send "Fiber #{i}: Hello!"
    end
    puts chan.receive
end

Fiber 0 has the longest sleep (5 seconds), followed by Fiber 1 (4 seconds) and so on…

I expect that after 1 second the output should be Fiber 4: Hello;
after 2 seconds the output should be Fiber 3: Hello, …
At the very least, the Fibers should not be in order starting from 0.

However, I ran the code a few times and it waits about 5 seconds to output
Fiber 0: Hello!
Fiber 1: Hello!
Fiber 2: Hello!
Fiber 3: Hello!
Fiber 4: Hello!
That is, the sleep 5 in Fiber 0 does not let any other fibers run until that fiber is completed. My question is what am I doing wrong. If the code is concurrent, shouldn’t the program go to another fiber which is ready when the first one is taking so long.

Thanks for your help, and thanks to the creators of Crystal for creating it.

You are calling chan.receive after each creation, it waits until Fiber finishes execution.

If you do

chan = Channel(String).new
5.times do |i|
    spawn do
        sleep 5-i
        chan.send "Fiber #{i}: Hello!"
    end
end
5.times do |i|
   puts chan.receive
end

order of messages will match your expectations.

6 Likes

Thanks! I realize the mistake I made. Appreciate your help.