I'm seeing some behavior with `AsyncCondition`s (on 0.5) that I don't
understand. I'm not sure if it's a bug or expected behavior.
Here’s a minimal example that doesn’t work the way I expect:
begin # wrapped for easy REPL-pasting
asynccond = Base.AsyncCondition()
waitcond = Condition()
n = 0
ccall(:uv_async_send, Cint, (Ptr{Void}, ), asynccond.handle) # this seems like
it shouldn't have any effect
@async begin
global n
n += 1
wait(asynccond)
n += 1
notify(waitcond)
end
yield() # give the async task a chance to run
println("waiting, n: $n")
ccall(:uv_async_send, Cint, (Ptr{Void}, ), asynccond.handle)
wait(waitcond)
# if we get here then the waiter was successfully woken
println("woke, n: $n")
end
Here’s what I’d expect to happen:
The first uv_async_send wouldn’t do anything because there are no tasks waiting
on the AsyncCondition.
The async task is added to the scheduler
the main task hits the first yield(), which switches to the async task
the async task blocks waiting on asynccond, which hands control back to the
main task
we print out n from the main task
this call to uv_async_send should put the async task back in the schedule queue
the main task blocks waiting on waitcond, which hands control back to the async
task
the async task notifies waitcond, which should add the main task back to the
schedule queue, then that task is complete
the main task prints the “woke” message
Instead it prints "waiting, n: 1”, then hangs.
It seems like the async task is never waking up from waiting on asynccond. If I
remove the first `uv_async_send` or add a `yield()` immediately after it, then
it works as expected.
Any ideas what’s going on?
-s