mirror of
https://github.com/pesde-pkg/scripts.git
synced 2024-12-12 15:00:37 +00:00
48 lines
1.1 KiB
Text
48 lines
1.1 KiB
Text
|
--- 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("recevied 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
|