# Timed loop

**URL:** https://discourse.julialang.org/t/timed-loop/48802
**Category:** General Usage
**Tags:** question
**Created:** [October 22, 2020, 6:38am UTC](https://discourse.julialang.org/t/timed-loop/48802 "2020-10-22T06:38:41Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [October 22, 2020, 6:38am UTC](https://discourse.julialang.org/t/timed-loop/48802/1 "2020-10-22T06:38:41Z")

</div>

I’m running a loop asynchronously. I’d like to have each iteration take at most `max_ns` nanoseconds. Here’s what i have so far:

```julia
function wait4it(t₀, max_ns)
    t₁ = time_ns()
    t = t₁ - t₀
    if t < max_ns
        s = 1e-9*(max_ns - t)
        sleep(s)
    end
    nothing
end
max_ns = 10^9
@async while true
    t₀ = time_ns()
    sleep(0.1) # and things
    wait4it(t₀, max_ns)
end

```

But I’m wondering if there is anything similar/better out there?

---

<div class="post-metadata">

### Author: ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)
#### Post date: [October 22, 2020, 7:03am UTC](https://discourse.julialang.org/t/timed-loop/48802/2 "2020-10-22T07:03:22Z")

</div>

Maybe this discussion is relevant? [Break function on time limit](https://discourse.julialang.org/t/break-function-on-time-limit/7376)

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [October 22, 2020, 7:19am UTC](https://discourse.julialang.org/t/timed-loop/48802/3 "2020-10-22T07:19:08Z")

</div>

Thanks! I edited my implementation following some of the ideas there (but by all means not all).

---

<div class="post-metadata">

### Author: ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)
#### Post date: [October 22, 2020, 7:26am UTC](https://discourse.julialang.org/t/timed-loop/48802/4 "2020-10-22T07:26:07Z")

</div>

We have [`timedwait`](https://docs.julialang.org/en/v1/base/parallel/#Base.timedwait) in Base (but this polls) or you could follow the following pattern:

```julia
cond = Condition()
Timer(x->notify(cond), max_time)
t = @async begin
    # do stuff
    notify(cond)
end
wait(cond)
t.state == :done ? fetch(t) : :timeout

```

see also: [How to wait on a condition for tasks](https://discourse.julialang.org/t/how-to-wait-on-a-condition-for-tasks/48023)

Better yet to put it in a function! Then you can return a value or a timeout.

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [October 22, 2020, 7:46am UTC](https://discourse.julialang.org/t/timed-loop/48802/5 "2020-10-22T07:46:32Z")

</div>

I hope I interpreted your code correctly: I assumed you gave an example of what one iteration would look like, i.e. the body of the `while`/`for` loop.

I modified your example in the following way:

```julia
max_s = 1
cond = Condition()
for i in 1:5
    Timer(_ -> notify(cond), max_s)
    sleep(0.1) # and things
    wait(cond)
    @show i
end

```

because there is no need to `async` the stuff that’s done in the loop – I don’t want the loop to `continue` unless that iteration is done. It worked well, except when the time needed to complete one iteration was longer than `max_s`, for instance if you replace

```julia
sleep(0.1) # and things

```

with

```julia
sleep(2) # and things

```

it gets stuck on the `wait` statement and never completes.

---

<div class="post-metadata">

### Author: ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)
#### Post date: [October 22, 2020, 8:01am UTC](https://discourse.julialang.org/t/timed-loop/48802/6 "2020-10-22T08:01:40Z")

</div>

No, my code is meant to avoid `sleep` entirely:

My code has three steps:

1. setup a **condition**
2. startup **two tasks** : a timer task and a worker task, whichever finishes first notifies the condition.
3. **wait** for the condition (in the main process) and return the result or the timeout.

---

<div class="post-metadata">

### Author: ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)
#### Post date: [October 22, 2020, 8:44am UTC](https://discourse.julialang.org/t/timed-loop/48802/7 "2020-10-22T08:44:36Z")

</div>

A working version is:

```julia
function twait(f::Function, timeout::Real=5)
    cond = Condition()
    Timer(x->notify(cond), timeout)
    t = @async begin
        res = f()
        notify(cond)
        res
    end
    wait(cond)
    t.state == :done ? fetch(t) : :timeout
end

```

If then we have a “heavy” computation, we can do:

```julia
heavy(t) = (sleep(t); return t) # a heavy computation taking t seconds

julia> twait(2) do
           heavy(1)
       end
1

julia> twait(2) do
           heavy(3)
       end
:timeout

```

In the second case we get a timeout since 2 \< 3.

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [October 26, 2020, 8:53am UTC](https://discourse.julialang.org/t/timed-loop/48802/8 "2020-10-26T08:53:23Z")

</div>

First and foremost, thank you very much @pbayer, I didn’t know about `Timer` and I learned something new with the `@async` call to the “heavy” function that allowed the `wait` to actually work.

I, of course, completely botched the description of what it was I _actually_ needed… I meant to ask for “…each iteration [to] take at ~~most~~ **least** ~~`max_ns`~~ **`min_ns`** nanoseconds…”, which lead to my great confusion. But adapting your answer to my needs was simple:

```julia
function twait(f, mint)
    cond = Condition()
    Timer(x->notify(cond), mint)
    t = @async $f()
    wait(cond)
    fetch(t)
end

```

So thanks again!

---

<div class="post-metadata">

### Author: ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)
#### Post date: [October 26, 2020, 9:10am UTC](https://discourse.julialang.org/t/timed-loop/48802/9 "2020-10-26T09:10:53Z")

</div>

> [@yakir12](#):
>
> `t = @async $f()`

very welcome!

Can I learn why do you interpolate `$f()` into `@async`?

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [October 26, 2020, 11:46am UTC](https://discourse.julialang.org/t/timed-loop/48802/10 "2020-10-26T11:46:09Z")

</div>

I don’t have any good reasons to, `f` being a function and not a variable. But when I `@btime`:ed this code I got a small residual (instead of 2 s it took 2.002 s) and I was experimenting to see if interpolating `f` would make a difference… It didn’t.

In the case where `f` doesn’t have anything to return (side affects are mutating some other variable in place), replacing the `fetch(t)` with `wait(t)` doesn’t change the results above either. In any case, that residual is negligent.
