# Can I rely on sleep waking up from a call to yield(task)

**URL:** <https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910>\
**Category:** General Usage\
**Created:** [July 28, 2019, 2:16pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910 "2019-07-28T14:16:33Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [July 28, 2019, 2:16pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/1 "2019-07-28T14:16:33Z")

</div>

The documentation for sleep() doesn’t mention that yield wakes it up, which I guess makes it an undocumented feature…But I’d really like to utilize that if possible…

Example:

```julia
using Dates

task = schedule(Task() do
    sleepAt = now()
    sleep(10)
    println("Slept for $(now() - sleepAt)")
end)

sleep(2)
yield(task)

```

If not I can use the wait() call on a condition that’s never triggered. (Triggering it on shutdown is possible, but would require that these tasks be treated special from the other tasks during shutdown…and I’d prefer to avoid that.)

---

<div class="post-metadata">

**Author:** ![jpsamaroo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpsamaroo/32/46804_2.png) [@jpsamaroo](https://discourse.julialang.org/u/jpsamaroo)\
**Post date:** [July 28, 2019, 6:14pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/2 "2019-07-28T18:14:55Z")

</div>

It’s not necessarily that `yield()` wakes up `sleep()` calls specifically, but instead that once the timer backing a `sleep()` call has elapsed, the task that contains that `sleep()` call is now eligible to be woken up by the scheduler (which a `yield()` call may cause to happen). This is also true for tasks waiting on I/O or other syscalls, with the obvious difference being that their condition for waking their waiting task is different than for `sleep()`.

If your goal is to wait on a task to wake up, then you’ll need to place a `Condition()` within the task and `notify()` it once your task has woken up (which a `wait()` call can then wait on). If you’re just waiting for the sleeping task to complete, then just `wait()` on it.

EDIT: To answer the question in your title, I would say that no, you cannot assume that a `yield()` call will wake up your task, because you can arbitrarily many tasks waiting in the scheduler queue ahead of your now-woken task that may be scheduled first. However, if we assume that the scheduler runs over the queue round-robin style, then yes you can assume that your sleeping task has woken once the `yield()` call returns, because the `yield()`-ing task will end up executing chronologically after the previously sleeping task executes.

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [July 28, 2019, 9:06pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/3 "2019-07-28T21:06:15Z")

</div>

Okay so taking your answer it’s an undocumented reaction, because with the above code, the task “wakes up” after 2 seconds not 10.

Reading the `wait` documentation closer it only mentions the “no argument” version waiting for an undefined period and only being restarted in response to a `schedule` or `yieldto` call. The documentation for `yieldto` specifically mentions `Its use is discouraged.` But the documentation for `yield` says it calls schedule for the task, so I guess that works.

If I don’t have a documented way to break a sleep then I guess I’ll have to use 2 task, one that does the actual work, that I can ensure is stopped at shutdown (by setting a shutdown flag and notifying it’s condition) and a second that periodically wakes up and trigger’s the first’s condition.

Granted the documentation for `wait` say it’s often in a while loop to ensure a waited-for condition is met before proceeding…and the condition object is edge triggered so I can’t check that…ugh it’s either boolean channels or more flags.

---

<div class="post-metadata">

**Author:** ![jpsamaroo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpsamaroo/32/46804_2.png) [@jpsamaroo](https://discourse.julialang.org/u/jpsamaroo)\
**Post date:** [July 29, 2019, 11:32am UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/4 "2019-07-29T11:32:48Z")

</div>

> [@pixel27](#):
>
> Okay so taking your answer it’s an undocumented reaction, because with the above code, the task “wakes up” after 2 seconds not 10.

Sorry, I didn’t realize that this was unexpected; `yield()` will immediately return if there are no other tasks to be scheduled, effectively making it a no-op. If that 10 second timer hasn’t elapsed, it is not possible or safe to wake the task.

> [@pixel27](#):
>
> If I don’t have a documented way to break a sleep

So this is a new requirement that wasn’t mentioned before (or I didn’t notice it). I think it would help if you could give a more real-world example of what you’re trying to accomplish, otherwise I feel like I won’t be as useful in giving you advice.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [July 29, 2019, 12:01pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/5 "2019-07-29T12:01:01Z")

</div>

To be fair, your example code does produce an error that crashes julia 1.1 a couple seconds later:

```julia
julia> using Dates

julia> task = schedule(Task() do
           sleepAt = now()
           sleep(10)
           println("Slept for $(now() - sleepAt)")
       end)
Task (runnable) @0x00007fcbc60fc760

julia> sleep(2); yield(task)
Slept for 3265 milliseconds

julia> ERROR: schedule: Task not runnable
Stacktrace:
 [1] enq_work at ./event.jl:88 [inlined]
 [2] #schedule#443(::Bool, ::Function, ::Task, ::EOFError) at ./event.jl:134

```

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [July 29, 2019, 12:42pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/6 "2019-07-29T12:42:40Z")

</div>

Ahhh, that’s interesting I had not seen that crash on version 1.1.1. However if I add a sleep() after the yield(task) so now I see the crash…Well that options is out.

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [July 29, 2019, 12:59pm UTC](https://discourse.julialang.org/t/can-i-rely-on-sleep-waking-up-from-a-call-to-yield-task/26910/7 "2019-07-29T12:59:37Z")

</div>

Real world examples get long, but here you go, given everything I’ve read/seen it sounds like I’m going to have to resort to this basic flow:

```julia
using Dates
using Base.Threads

shutdown = Atomic{Bool}(false)
wakeup = Channel{Bool}(3)

wakeTask = schedule(Task() do
    local wakeAt = now() + Second(10)

    while shutdown[] == false
        if now() >= wakeAt
            put!(wakeup, true)
            wakeAt = now() + Second(10)
        else
            sleep(Dates.value(wakeAt-now()) / 1000)
        end
    end
end)

workTask = schedule(Task() do
    while take!(wakeup) == true
        println("Heart beat")
    end
    println("Cleanup")
end)

function stop()
    atomic_xchg!(shutdown, true)
    put!(wakeup, false)
    wait(workTask)
end

```

I guess I was just hoping for less code. Which an early way to wake up sleep would give…or a wait with a timeout. But I don’t have either of those, so this is probably what I’ll use.

- The wakeTask feels gratuitous, but I don’t see a way around it.
- The channel is dangerous in the aspect that if the workTask stops unexpectedly/crashes then `stop()` could hang forever. So I’ll want to add protection for that.
- I can’t really use a Condition because the wait documentation says wait could return **before** the condition is set and I don’t want my heart beating too fast.
- I might be able to remove the checks around sleep, it’s documentation doesn’t mention waking up early…

In my real world the delays are not in seconds but hours…so I really would like a way to shutdown workTask early so it can save it’s state.
