Last active
December 15, 2024 18:38
-
-
Save stravant/7a11ea1147d742463b116a3793e112cb to your computer and use it in GitHub Desktop.
An implementation of RBXScriptSignal which sacrifices correctness to be as performant as possible
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------------------------------------------------------------------------------- | |
-- Fast Signal-like class -- | |
-- This is a Signal class that is implemented in the most performant way -- | |
-- possible, sacrificing correctness. The event handlers will be called -- | |
-- directly, so it is not safe to yield in them, and it is also not safe to -- | |
-- connect new handlers in the middle of a handler (though it is still safe -- | |
-- for a handler to specifically disconnect itself) -- | |
-------------------------------------------------------------------------------- | |
local Signal = {} | |
Signal.__index = Signal | |
local Connection = {} | |
Connection.__index = Connection | |
function Connection.new(signal, handler) | |
return setmetatable({ | |
_handler = handler, | |
_signal = signal, | |
}, Connection) | |
end | |
function Connection:Disconnect() | |
self._signal[self] = nil | |
end | |
function Signal.new() | |
return setmetatable({}, Signal) | |
end | |
function Signal:Connect(fn) | |
local connection = Connection.new(self, fn) | |
self[connection] = true | |
return connection | |
end | |
function Signal:DisconnectAll() | |
table.clear(self) | |
end | |
function Signal:Fire(...) | |
if next(self) then | |
for handler, _ in pairs(self) do | |
handler._handler(...) | |
end | |
end | |
end | |
function Signal:Wait() | |
local waitingCoroutine = coroutine.running() | |
local cn; | |
cn = self:Connect(function(...) | |
cn:Disconnect() | |
task.spawn(waitingCoroutine, ...) | |
end) | |
return coroutine.yield() | |
end | |
function Signal:Once(fn) | |
local cn; | |
cn = self:Connect(function(...) | |
cn:Disconnect() | |
fn(...) | |
end) | |
return cn | |
end | |
return Signal | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment