Skip to content

Instantly share code, notes, and snippets.

@lucasmz-dev
Last active December 2, 2021 00:35
Show Gist options
  • Save lucasmz-dev/b2653106adecd9b18eb88f8e65589ec9 to your computer and use it in GitHub Desktop.
Save lucasmz-dev/b2653106adecd9b18eb88f8e65589ec9 to your computer and use it in GitHub Desktop.
GoodSignalv2
-- https://github.com/RBLXUtils/FastSignal/blob/main/src/ReplicatedStorage/FastSignal/Immediate.lua
-- FastSignal's Immediate Mode ended up being made from this code, with some modifications.
-- This gist is no longer updated and may contain bugs, check out FastSignal Immediate.
local ScriptSignal = {}
ScriptSignal.__index = ScriptSignal
local ScriptConnection = {}
ScriptConnection.__index = ScriptConnection
local FreeThread: thread? = nil
local function RunHandler(handle, ...)
local thread = FreeThread :: thread
FreeThread = nil
handle(...)
FreeThread = thread
end
local function RunHandlerInFreeThread(...)
RunHandler(...)
while true do
RunHandler( coroutine.yield() )
end
end
function ScriptSignal.new()
return setmetatable({
_active = true,
_head = nil
}, ScriptSignal)
end
function ScriptSignal:Connect(
handle: (...any) -> ()
)
assert(
typeof(handle) == 'function',
"Must be function"
)
if self._active == false then
return setmetatable({
Connected = false
}, ScriptConnection)
end
local _head = self._head
local node = {
_signal = self,
_handle = handle,
_connection = nil,
_next = _head,
_prev = nil
}
if _head then
_head._prev = node
end
self._head = node
local connection = setmetatable({
Connected = true,
_node = node
}, ScriptConnection)
node._connection = connection
return connection
end
function ScriptSignal:ConnectOnce(
handle: (...any) -> ()
)
assert(
typeof(handle) == 'function',
"Must be function"
)
local connection
connection = self:Connect(function(...)
if connection == nil then
return
end
connection:Disconnect()
connection = nil
handle(...)
end)
end
function ScriptSignal:Wait(): (...any)
local thread do
thread = coroutine.running()
local connection
connection = self:Connect(function(...)
if connection == nil then
return
end
connection:Disconnect()
connection = nil
task.spawn(thread, ...)
end)
end
return coroutine.yield()
end
function ScriptSignal:Fire(...)
local node = self._head
while node ~= nil do
if FreeThread == nil then
FreeThread = coroutine.create(RunHandlerInFreeThread)
end
task.spawn(
FreeThread :: thread,
node._handle,
...
)
node = node._next
end
end
function ScriptSignal:DisconnectAll()
local node = self._head
while node ~= nil do
node._connection:Disconnect()
node = node._next
end
end
function ScriptSignal:Destroy()
if self._active == false then
return
end
self:DisconnectAll()
self._active = false
end
function ScriptConnection:Disconnect()
if self.Connected == false then
return
end
self.Connected = false
local _node = self._node
local _prev = self._prev
local _next = self._next
if _next then
_next._prev = _prev
end
if _prev then
_prev._next = _next
else
-- _node == _signal._head
_node._signal._head = _next
end
_node._connection = nil
self._node = nil
end
export type ScriptSignal = typeof(
setmetatable({}, ScriptSignal)
)
export type ScriptConnection = typeof(
setmetatable({Connected = true}, ScriptConnection)
)
return ScriptSignal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment