Skip to content

Instantly share code, notes, and snippets.

@lucasmz-dev
Created November 20, 2021 00:33
Show Gist options
  • Save lucasmz-dev/ea4bbd96b87915cbf539ff63d21f38c1 to your computer and use it in GitHub Desktop.
Save lucasmz-dev/ea4bbd96b87915cbf539ff63d21f38c1 to your computer and use it in GitHub Desktop.
SimpleSignal
export type ScriptSignal = {
_active: boolean,
_head: ScriptConnection?,
IsActive: (ScriptSignal) -> boolean,
Connect: (
ScriptSignal,
handler: (...any) -> ()
) -> ScriptConnection,
Wait: (ScriptSignal) -> (...any),
Fire: (ScriptSignal, ...any) -> (),
DisconnectAll: (ScriptSignal) -> (),
Destroy: (ScriptSignal) -> (),
}
export type ScriptConnection = {
Connected: boolean,
Disconnect: (ScriptConnection) -> (),
_signal: ScriptSignal,
_handler: (...any) -> (),
_next: ScriptConnection?,
_previous: ScriptConnection?,
}
local function ScriptConnection(
signal: ScriptSignal,
handler: (...any) -> ()
): ScriptConnection
local self = {
Connected = true,
_signal = signal,
_handler = handler,
_next = nil,
_previous = nil
}
function self:Disconnect()
if self.Connected ~= true then
return
end
self.Connected = false
local next = self._next
local previous = self._previous
if next ~= nil then
next._previous = previous
end
if previous ~= nil then
previous._next = next
else
self._signal._head = next
end
end
return self
end
local function ScriptSignal(): ScriptSignal
local self = {
_active = true,
_head = nil
}
function self:IsActive()
return self._active == true
end
function self:Connect(handler)
assert(
typeof(handler) == 'function',
"Must be function"
)
local connection = ScriptConnection(self, handler)
if self._active ~= true then
connection.Connected = false
return connection
end
local head = self._head
connection._next = head
if head ~= nil then
head._previous = connection
end
self._head = connection
return connection
end
function self:Wait()
local thread do
thread = coroutine.running()
local connection = nil
connection = self:Connect(function(...)
if connection == nil then
return
end
connection:Disconnect()
connection = nil
task.spawn(thread, ...)
end)
end
return coroutine.yield()
end
function self:Fire(...)
local connection = self._head
while connection ~= nil do
task.defer(
connection._handler,
...
)
connection = connection._next
end
end
function self:DisconnectAll()
local connection = self._head
while connection ~= nil do
connection.Connected = false
connection = connection._next
end
self._head = nil
end
function self:Destroy()
if self._active ~= true then
return
end
self._active = false
self:DisconnectAll()
end
return self
end
return ScriptSignal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment