--- An MPSC synchronization primitive powered by Lua upvalues which retains only 
--- one value at a time.

--- ## Usage
--- ```luau
--- local send, recv = watch((nil :: any) :: string)
--- task.delay(5, send, "hello, world!")
--- task.spawn(function()
---     local value = recv()
---     print("received value:", value)
--- end)
--- ```
type Watch<T> = {
    value: T?,
    receivers: { thread },
}

--- Crates a new `Watch` channel, returning its send and receive handles.
local function chan<T>(_phantom: T): ((T) -> (), () -> T?)
    local watch: Watch<T> = {
        value = nil,
        receivers = {},
    }

    local function send(value: T)
        watch.value = value

        for _, receiver in watch.receivers do
            coroutine.resume(receiver, value)
        end
    end

    local function recv(): T
        local value = watch.value
        watch.value = nil
        
        if value == nil then
            table.insert(watch.receivers, coroutine.running())
            return coroutine.yield()
        end
        
        return value :: T
    end

    return send, recv
end

return chan