I’m calling a function in an external API with ccall. That C function makes an IO operation internally. If I call it with
@async will the scheduler yield automatically, or do I have to hook this to libuv to make it async?
More generally, what makes an
@async call yield to another task in parallel?
You have to hook it to libuv. The simplest way is probably to pass
@cfunction(yield, Nothing, ()) as a callback function of type
void (*yield)() to C, allowing you to call the Julia
yield() function directly.
But then I don’t think you can do the IO while calling
yield? I suppose all the IO has to go through the event loop in order to do them concurrently (non-blockingly).
IIUC, if you need to do IO without touching libuv’s IO interface, then you have to do it in a different thread. To ping Julia to come back to the C function in the main thread, you call
uv_async_send(cond.handle) from the IO thread once the IO is finished, where this
cond is created with
Base.AsyncCondition. You can call Julia code
wait(cond) in the thread that initialized Julia. During this
wait(cond), Julia can run other tasks and block until
uv_async_send. (Not sure if this is the only solution. It’s just what I know.)
The experimental macro
@threadcall addresses this issue, right? I mean, if I want to make an external function call async.