Following is a example.
ch = Channel(UInt128).new
terminate = Channel(Nil).new
done = Channel(Nil).new
[1, 2, 3].each do |i|
spawn do
x = 0_u128
y = rand(5000000..10000000)
puts "6"*50
(1..y).each { |e| x += e }
puts "7"*50
ch.send x
puts "8"*50
end
end
spawn do
loop do
select
when value = ch.receive
puts "4"*50
p value
when terminate.receive?
puts "3"*50
break
end
end
done.close
puts "exiting loop fiber"
end
puts "1"*50
terminate.close
puts "2"*50
done.receive?
puts "end"
When i run above code, i get result like following:
11111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222
66666666666666666666666666666666666666666666666666
77777777777777777777777777777777777777777777777777
66666666666666666666666666666666666666666666666666
77777777777777777777777777777777777777777777777777
66666666666666666666666666666666666666666666666666
77777777777777777777777777777777777777777777777777
44444444444444444444444444444444444444444444444444
31855631199211
44444444444444444444444444444444444444444444444444
45854814984355
44444444444444444444444444444444444444444444444444
15626260923210
33333333333333333333333333333333333333333333333333
exiting loop fiber
88888888888888888888888888888888888888888888888888
88888888888888888888888888888888888888888888888888
88888888888888888888888888888888888888888888888888
end
If I change the 20th line of code from ch.send x
into Fiber.yield
, like following:
ch = Channel(UInt128).new
terminate = Channel(Nil).new
done = Channel(Nil).new
[1, 2, 3].each do |i|
spawn do
x = 0_u128
y = rand(5000000..10000000)
puts "6"*50
(1..y).each { |e| x += e }
puts "7"*50
Fiber.yield
puts "8"*50
end
end
spawn do
loop do
select
when value = ch.receive
puts "4"*50
p value
when terminate.receive?
puts "3"*50
break
end
end
done.close
puts "exiting loop fiber"
end
puts "1"*50
terminate.close
puts "2"*50
done.receive?
puts "end"
I got new output like following:
11111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222
66666666666666666666666666666666666666666666666666
77777777777777777777777777777777777777777777777777
66666666666666666666666666666666666666666666666666
77777777777777777777777777777777777777777777777777
66666666666666666666666666666666666666666666666666
77777777777777777777777777777777777777777777777777
33333333333333333333333333333333333333333333333333
exiting loop fiber
end
My question is, why the first code output following 888888
88888888888888888888888888888888888888888888888888
88888888888888888888888888888888888888888888888888
88888888888888888888888888888888888888888888888888
but it does not for the second code?
the first code scheduler switch to the blocked fibers in the each
before loop's fiber
exit so puts "8"*50
, but, it’s does not happen for second code.
What are the differences when fiber scheduler works for above two code?
Before switch back to the done.receive
in the main fiber, main fiber will waiting for all spawned fiber to be fulled blocked/exit or not? above two codes get opposite result, causing me very confused.
Test on 1.14.0, thanks
EDIT:
If replace ch.send x
with sleep 1
or sleep 0
, the result same as Fiber.yield
, only ch.send x
behavior different.
The only explanation I can think of is that Fiber scheduler will tries switch to fibers which blocked by channel operation (e.g. ch.send
) and execute them before main fiber
exit, but this is not the case when used with Fiber.yield/sleep 0/sleep 1
?