# Interrupting wait(Threads.Event())

**URL:** https://discourse.julialang.org/t/interrupting-wait-threads-event/105047
**Category:** General Usage
**Tags:** concurrency
**Created:** [October 17, 2023, 3:48am UTC](https://discourse.julialang.org/t/interrupting-wait-threads-event/105047 "2023-10-17T03:48:07Z")
**Posts on this page:** 1
**Showing post:** 5

<div class="post-metadata">

### Author: ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)
#### Post date: [October 18, 2023, 2:54am UTC](https://discourse.julialang.org/t/interrupting-wait-threads-event/105047/5 "2023-10-18T02:54:47Z")

</div>

That’s very similar to what I had in my original post except that you use a `dummy_channel` instead of my `dummy_event`. Correspondingly, your proposal leads to the same problems as mine. However, I came to realise that I never explicitly mentioned one of these problems, so before we continue the discussion I should probably first fix that.

Going back to the solution described in the original post, avoiding the resource leak is _in principle_ straightforward: all I have to do is to “close” the original event that I’m waiting for. Unfortunately, events don’t have an API analogous to `close()`, so for the purpose of this argument I’ll just notify it instead.

```julia
# Actual event I want to wait for
event = Threads.Event() 

dummy_event = Threads.Event() # Helper event
@async begin
    wait(event)
    notify(dummy_event)
end
Timer(t->notify(dummy_event), 1.0)
wait(dummy_event)

# This should be `close(event)`. The main point here 
# is to kill off the helper task somehow. 
notify(event) 

```

Of course, the problem with this solution is that we mess with the original `event` variable in a way that will likely break other code using it. Such other code could be made robust against this type of meddling, but that would be fragile and doesn’t scale well, so it’s far from an ideal solution.

Looking at things from this perspective, perhaps the missing piece in Julia’s async story is a way to `close()` a listener without closing the object that it is listening on. That would allow us to do things like this:

```julia
julia> c = Condition()
       l = listen(c)
       @async close(l) # Close the listener, but leave the original condition untouched.
       wait(l)
ERROR: InvalidStateException: Listener is closed

```

Fortunately, Julia’s open and simple internals allow us to just go ahead and implement such a primitive ourselves:

```julia
mutable struct Listener{T}
    object::T
    task::Union{Nothing, Task}
end

listen(object) = Listener(object, nothing)

function Base.wait(listener::Listener)
    listener.task = current_task()
    try
        wait(listener.object)
    finally
        listener.task = nothing
    end
end

function Base.close(listener::Listener)
    if (
        !isnothing(listener.task) &&
        !isnothing(listener.task.queue)
    )
        Base.list_deletefirst!(listener.task.queue, listener.task)
        schedule(
            listener.task,
            InvalidStateException("Listener is closed", :closed);
            error = true
        )
    end
end

```

Admittedly, I’m messing around here with things that I only just barely understand, so I’d be curious to hear what more knowledgeable people than me think about this!

---

_[View the full topic](https://discourse.julialang.org/t/interrupting-wait-threads-event/105047)._
