Timedwait() doesn't time out

I’m new to Julia’s multi-threading and frankly Julia itself. I’ve been reading up on the API docs and trying various things on REPL. In particular, I was playing with the timedwait() method which IIUC runs a given function either until it finishes or the deadline has been reached. So to test my understanding I did:

julia> function test()                                                                                                                                  
         sleep(2)                                                                                                                                       
         return true                                                                                                                                    
       end                                                                                                                                              
test (generic function with 1 method)

julia> timedwait(test, 1.0)                                                                                                                             
:ok

In other words, I defined a function that simply sleeps for 2 seconds and returns true. And I ran timedwait() on that method with a timeout of 1.0, but this returned :ok. What am I missing here?

1 Like

The callback function is called multiple times (until returning true). Your function always return true so timedwait returns :ok. I agree that the docstring for timedwait isn’t very clear though so would be good to improve that.

Here is an example:

julia> cb = function()
           @info "Callback called"
           return false # always false so this will time out
       end;

julia> timedwait(cb, 1.0)
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
[ Info: Callback called
:timed_out

So it seems like the intended purpose is for the callback function to check if something is available in a Channel or if a mutex has been released or whatever, and then if it has finally return true, otherwise return false. Then when the timeout occurs, you can kill the task that was supposed to provide the value to the channel or similar?

What I was hoping to do was to run a series of simulations in parallel using Threads.@spawn, and use @sync to wait for the simulations to finish, but not for more than a certain timeout. My initial thought was to do sth like the following:

function run_simulations()
  @sync for i = 1:n
    Threads.@spawn simulate()
  end
end

timedwait(run_simulations, timeout)

But based on @fredrikekre’s answer the above doesn’t quite do what I wanted as the callback gets called continuously. Is there an easy way to achieve this with basic Julia APIs? Perhaps store references to the Tasks returned from the @spawn calls and continuously check if everything is done inside the callback?

I think what you want is that your simulate() code should check to see if it has been sent a message to terminate prematurely (on a Channel).

Yes, do this, then run timedwait and at the end of the timeout if the callback hasn’t collected all the results, send the “abort” message over the channel to the simulate code.

What this seems to do is avoid an unsafe exit via “throw an exception” into the task… potentially leaving things in an inconsistent state and preventing further safe computation. I’m not clear on if there’s a safe way to simply “kill” a task.

1 Like