scripts/.lune/lib/channel.luau

49 lines
985 B
Text
Raw Permalink Normal View History

2024-12-08 17:42:05 +00:00
--- 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> = {
2024-12-08 18:30:38 +00:00
value: T?,
receivers: { thread },
2024-12-08 17:42:05 +00:00
}
--- Creates a new `Watch` channel, returning its send and receive handles.
2024-12-08 17:42:05 +00:00
local function chan<T>(_phantom: T): ((T) -> (), () -> T?)
2024-12-08 18:30:38 +00:00
local watch: Watch<T> = {
value = nil,
receivers = {},
}
2024-12-08 17:42:05 +00:00
2024-12-08 18:30:38 +00:00
local function send(value: T)
watch.value = value
2024-12-08 17:42:05 +00:00
2024-12-08 18:30:38 +00:00
for _, receiver in watch.receivers do
coroutine.resume(receiver, value)
end
end
2024-12-08 17:42:05 +00:00
2024-12-08 18:30:38 +00:00
local function recv(): T
local value = watch.value
watch.value = nil
2024-12-08 17:42:05 +00:00
2024-12-08 18:30:38 +00:00
if value == nil then
table.insert(watch.receivers, coroutine.running())
return coroutine.yield()
end
2024-12-08 17:42:05 +00:00
2024-12-08 18:30:38 +00:00
return value :: T
end
2024-12-08 17:42:05 +00:00
2024-12-08 18:30:38 +00:00
return send, recv
2024-12-08 17:42:05 +00:00
end
return chan