NormalSignal is a fork of a BadSignal whose purpose is to simplify BadSignal for begginers while NOT losing any perfomance.
Why using NormalSignal?
The exact same Reason as to why people use custom signal libraries:
- Immediate execution unlike in BindableEvent with defered signal
-
better perfomance compare to BindableEvent
NormalSignal does replicate behavior of BindableEvent and allows you to do more specific optimizations such as :ConnectMain() (:Push(false) of a BadSignal)
In general its a very fast Signal library that is able to surpass most of signal libraries like GoodSignal by A LOT! (look at benchmarks bellow) thanks to its optimization methods.
Documentation:
Creating a Signal:
For the best perfomance (as you see on benchmarks) put a number with ammount of connections you want to have in this Signal.
local signal = NormalSignal(1)
Note: order in which you connect connections will affect the order on which connections will resume!
Connect
Connect works just like in BindableEvent which will connect a function to a Signal and upon firing will run a function inside a new thread!
local signal = NormalSignal(1)
signal:Connect(function()
end)
ConnectMain
ConnectMain works a little different to Connect becouse upon firing it will simply run this function without creating a new thread; VERY GOOD FOR PERFOMANCE AND YOU MUST PRIORITIZE USING IT INSTEAD OF CONNECT hower if function does have any yielding such as wait()/task.wait() it will cause a huge problems and in this case you must resort to using Connect instead!
local signal = NormalSignal(1)
signal:ConnectMain(function()
end)
Once
Once works similar to Once in a BindableEvent hower here it does return you a thread; Once will ALWAYS create a thread like Connect, you must avoid using :Disconnect if you are using this method and instead you will have to do it manually:
local signal = NormalSignal(1)
local thread = signal:Once(function()
end)
local needle:number? = table.find(signal._tsk,thread)
if needle then
table.remove(signal._tsk,needle)
end
--Once is now disconnected
Disconnect
As you can see (not meant to be used for threads:warning:
) refers that you must NOT pass thread into Disconnect from :Once or :Wait
Disconnect is used to disconnect a function from Signal, which does mean that you previously should’ve had cached referance to a function and should’ve avoided using anonimous function!Althrough that not a big deal becouse in BindableEvent for example you have to cache connections instead.
local signal = NormalSignal(1)
local function Hello()
end
signal:ConnectMain(Hello)
signal:Disconnect(Hello)
Fire
Fire works just like in BindableEvent, allowing you to pass arguments into all connected functions!
local signal = NormalSignal(1)
signal:ConnectMain(function(Action,Item)
print(`Im {Action} {Item}`)
end)
signal:Fire("Eating","Apple") -- print("Im Eating Apple")
Wait
Wait works the exact same way it works in BindableEvent Yielding untill you fire Signal from elsewhere and does return arguments Fire signal gave!
local signal = NormalSignal(1)
task.delay(10,function()
signal:Fire("You are now free!")
end)
local hi = signal:Wait()
print("Im resumed:",hi)
DisconnectAll
Disconnects absolutelly ALL connections in Signal and it doesn’t require you to pass any parameters to do so at all!
local signal = NormalSignal(1)
signal:Connect(function()
end)
signal:DisconnectAll()
Destroy
Destroys Signal, making it ready to be garbage collected!
local signal = NormalSignal(1)
signal:Destroy()
signal=nil
Benchmarks:
Creation
NormalSignal losing a tiny bit to BadSignal becouse NormalSignal has more methods.
t = 0
for ii=1,20 do
local h = os.clock()
for i=1,99999 do
NormalSignal(0)
end
t+=os.clock()-h
end
print(`NormalSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
for i=1,99999 do
BadSignal:new(9999)
end
t+=os.clock()-h
end
print(`BadSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
for i=1,99999 do
GoodSignal.new()
end
t+=os.clock()-h
end
print(`GoodSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
for i=1,99999 do
Instance.new("BindableEvent")
end
t+=os.clock()-h
end
print(`BindableEvent Creation: {t/20}`)
Connecting
Same problem as in previous benchmark
t = 0
for ii=1,20 do
local h = os.clock()
local normal = NormalSignal(99999)
for i=1,99999 do
normal:ConnectMain(BenchmarkFunc)
end
t+=os.clock()-h
end
print(`NormalSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local bad = BadSignal:new(99999)
for i=1,99999 do
bad:Push(false,BenchmarkFunc)
end
t+=os.clock()-h
end
print(`BadSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local good = GoodSignal.new()
for i=1,99999 do
good:Connect(BenchmarkFunc)
end
t+=os.clock()-h
end
print(`GoodSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local bindable = Instance.new("BindableEvent")
local event = bindable.Event
for i=1,99999 do
event:Connect(BenchmarkFunc)
end
t+=os.clock()-h
end
print(`BindableEvent Creation: {t/20}`)
Firing
Somehow NormalSignal won BadSignal wth
t = 0
for ii=1,20 do
local h = os.clock()
local normal = NormalSignal(99999)
normal:ConnectMain(BenchmarkFunc)
for i=1,99999 do
normal:Fire()
end
t+=os.clock()-h
end
print(`NormalSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local bad = BadSignal:new(99999)
bad:Push(false,BenchmarkFunc)
for i=1,99999 do
bad:Fire()
end
t+=os.clock()-h
end
print(`BadSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local good = GoodSignal.new()
good:Connect(BenchmarkFunc)
for i=1,99999 do
good:Fire()
end
t+=os.clock()-h
end
print(`GoodSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local bindable = Instance.new("BindableEvent")
bindable.Event:Connect(BenchmarkFunc)
for i=1,99999 do
bindable:Fire()
end
t+=os.clock()-h
end
print(`BindableEvent Creation: {t/20}`)
Benchmarking have been done with something like that:
--!optimize 2
--!strict
--!native
local NormalSignal = require(script:WaitForChild("NormalSignal"))
local BadSignal = require(script:WaitForChild("BadSignal"))
local GoodSignal = require(script:WaitForChild("GoodSignal"))
local function BenchmarkFunc()
end
local t:number=0
t = 0
for ii=1,20 do
local h = os.clock()
local normal = NormalSignal(99999)
normal:ConnectMain(BenchmarkFunc)
for i=1,99999 do
normal:Fire()
end
t+=os.clock()-h
end
print(`NormalSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local bad = BadSignal:new(99999)
bad:Push(false,BenchmarkFunc)
for i=1,99999 do
bad:Fire()
end
t+=os.clock()-h
end
print(`BadSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local good = GoodSignal.new()
good:Connect(BenchmarkFunc)
for i=1,99999 do
good:Fire()
end
t+=os.clock()-h
end
print(`GoodSignal Creation: {t/20}`)
t = 0
for ii=1,20 do
local h = os.clock()
local bindable = Instance.new("BindableEvent")
bindable.Event:Connect(BenchmarkFunc)
for i=1,99999 do
bindable:Fire()
end
t+=os.clock()-h
end
print(`BindableEvent Creation: {t/20}`)