######################################################################
# Signals are essentially waitable atomic booleans.
# -----
# Licensed under Apache License 2.0
module Signals
using Base.Threads

export Signal
mutable struct Signal
    flag::Bool
    notify::Condition
end
Signal() = Signal(false, Condition())

Base.lock(cb, signal::Signal, args...; kwargs...) = lock(cb, signal.notify, args...; kwargs...)
Base.lock(signal::Signal, args...; kwargs...) = lock(signal.notify, args...; kwargs...)
Base.unlock(signal::Signal, args...; kwargs...) = unlock(signal.notify, args...; kwargs...)
Base.notify(signal::Signal, args...; kwargs...) = notify(signal.notify, args...; kwargs...)

function Base.wait(signal::Signal)
    lock(signal.notify) do
        while !isset(signal)
            wait(signal.notify)
        end
    end
end

export isset
isset(signal::Signal) = signal.flag

export set
function set(signal::Signal)
    lock(signal) do
        signal.flag = true
        notify(signal)
    end
    nothing
end

export clear
function clear(signal::Signal)
    lock(signal) do
        signal.flag = false
        notify(signal)
    end
    nothing
end

end # module Signals
