Skip to content

Instantly share code, notes, and snippets.

@Fraktality
Created August 12, 2020 06:34
Show Gist options
  • Save Fraktality/cf847e235d305ee43e57dcf17dfc84fb to your computer and use it in GitHub Desktop.
Save Fraktality/cf847e235d305ee43e57dcf17dfc84fb to your computer and use it in GitHub Desktop.
Minimal signal datatype impl
local Connection = {} do
Connection.__index = Connection
function Connection.new(hook, signal)
return setmetatable({
_hook = hook,
_signal = signal,
_connected = true,
}, Connection)
end
function Connection:disconnect()
if not self._connected then
return
end
local connections = self._signal._connections
for i = #connections, 1, -1 do
if connections[i] == self then
table.remove(connections, i)
break
end
end
self._hook = nil
self._signal = nil
self._connected = false
end
function Connection:getConnected()
return self._connected
end
end
local Signal = {} do
Signal.__index = Signal
function Signal.new()
return setmetatable({
_connections = {},
_threads = {},
}, Signal)
end
function Signal:connect(hook)
local con = Connection.new(hook, self)
table.insert(self._connections, con)
return con
end
function Signal:wait()
table.insert(self._threads, coroutine.running())
return coroutine.yield()
end
function Signal:fire(...)
local threads = self._threads
local connections = {unpack(self._connections)}
for i = #threads, 1, -1 do
local t = threads[i]
self._threads[i] = nil
coroutine.resume(t, ...)
end
local ran = {}
for i = #connections, 1, -1 do
local con = connections[i]
if con and not ran[con] then
ran[con] = true
coroutine.wrap(con._hook)(...)
end
end
end
end
return Signal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment