Qestion1:
Because the max size of chnl is 0, the following code should be blocked. Why the following code is not blocked?
chnl = Channel() do ch
foreach(i -> put!(ch, i), 1:4) # not blocked
end;
The following is blocked.
chnl = Channel()
foreach(i -> put!(ch, i), 1:4) # blocked here
Question 2:
The following result is not as expected.
function take_channel(c)
d = take!(c)
println("get data: ", d)
p()
end
function p()
println("I am here")
end
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
@async take_channel(c)
put!(c, 2)
The output is
get data: 1 #why `get data 2` is not printed, and no `I am here`
Testing LDTSimulate tests passed
If I put the code in @testset the result looks as expected,
function take_channel(c)
d = take!(c)
println("get data: ", d)
p()
end
function p()
println("I am here")
end
@testset "test channel" begin
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
@async take_channel(c)
put!(c, 2)
end
The results are as expected.
get data: 1
Test Summary: |I am here
get data: 2
I am here
test channel | No tests
Testing LDTSimulate tests passed
chnl = Channel() do ch
foreach(i -> put!(ch, i), 1:4)
end
The inner function is blocked, but it’s scheduled asynchronously, so it doesn’t block the main thread. Basically that is similar to doing:
chnl = Channel()
@async foreach(i -> put!(ch, i), 1:4)
Issue 2 is has to do with scheduling and REPL. I believe if you do:
@sync begin
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
end
The @sync will cause the execution to pause and allow the @async task to finish. My guess is that the println() is giving up control which allows the REPL to execute again. You might also be able to do a sleep(1) after you do the put!(c, 1) which should give the async task time to finish.
note the Channel() constructor which is similar to Channel(0) creates an unbuffered channel i.e put! blocks until a matching take! is called. And vice-versa.
For me the question 2 works just fine.
function take_channel(c)
d = take!(c)
println("get data: ", d)
p()
end
function p()
println("I am here")
end
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1);
@async take_channel(c)
put!(c, 2);
And i get the expected output.
Thank you so much for your answer. The code you suggested works as expected. I am surprised that the default REPL does not run as @sync. But it also does not run as @async. There should be some different behaviour not described in the document.
@sync begin
c = Channel{Int64}(0)
@async take_channel(c) #
put!(c, 1)
end
I found a very clear explanation, much clearer than the document. Hope it could help other users.
When to use @sync and @async