Closed
Description
@sync @spawn @spawn f()
expands roughly to
let sync = Any[]
task1 = Task() do
task2 = Task() do
f()
end
task2.sticky = false
push!(sync, task2)
schedule(task2)
task2
end
task1.sticky = false
push!(sync, task1)
schedule(task1)
task1
end
This code itself is OK. However, I don't think the following code is thread-safe:
@sync begin
@spawn @spawn f()
@spawn @spawn g()
end
This is because push!(sync, task2)
for @spawn f()
and @spawn g()
can be executed in parallel. This came up in #34543 (comment)
How should it be fixed? Maybe expand @spawn ...
to something like below?
if $(Expr(:islocal, :sync))
local sync_sub = Any[]
task = Task() do
local sync = sync_sub
...
end
else
task = Task() do
...
end
end
task.sticky = false
if $(Expr(:islocal, :sync))
push!(sync, task)
@async begin
wait(task)
append!(sync, sync_sub) # merge sub-tasks
end
end
schedule(task)