There’s an issue.
When you create a signal, you save the index for that connection. But when another signal is disconnected, that index doesn’t get updated, so the disconnection for that connection won’t actually work (it might even disconnect a different connection).
?
I don’t update the index when doing :DisconnectAll()
or when the connection is the last one (which I’m assuming is what you’re referring to) because it doesn’t matter, the array is gonna be empty.
What about those in front? They have to get shifted too.
{1, 2, 3, 4}
-- After disconnecting '2':
{1, 3, 4}
-- They should get shifted too:
{1, 3, 4}
Hi, I am using what is called “swapback removal” for arrays, it is O(1) like linked lists, however with better memory locality (cuz array) and better iteration, at the cost of sacrificing a little order.
This is how swapback removal works, the last element is set to the current position and then the last element is set to nil, unlike shifting which is extremely slow at O(n).
What you described is shifting, this is swapback removal:
{1, 2, 3, 4}
{1, 3, 4}
{1, 4, 3}
In the case of SimpleSignal
, firing is so fast order almost doesn’t matter. So this was the choice of connection storage (mostly because it’s shorter to implement too)
I still don’t quite get it. You are setting the pos
value but never actually move it? The array and the pos
’ don’t match.
For example, let’s say I have 3 connections, A, B and C, in this array: {A, B, C}
And let’s say I call disconnect on A
A will get the last element (C), and externally manipulate its _pos
value to be A’s _pos
And then finally it will set its position in the array to C, and set C’s original location to nil
, turning the array into {C, B}.
All other elements are unaffected, so there is no need to manipulate anything else.
(Also I don’t really get what you mean by “moving” pos
?)
I meant move the value itself. You’re manipulating the _pos
values but never actually moving the array children?
?
I get it now. Sorry it took me this long to grasp.
Thanks for explaining it well.
I’ve found an issue.
Once and Wait connections disconnect themselves while it’s looping through the connections array, messing the loop up. You can try the following code out, C
never prints because it’s after a Once connection:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SimpleSignal = require(ReplicatedStorage.SimpleSignal)
local signal = SimpleSignal.new()
signal:Connect(function()
print("A")
end)
signal:Once(function()
print("B")
end)
signal:Connect(function()
print("C")
end)
signal:Fire()
Ahh yeah I can replicate the issue, I do have an idea on how to fix this, will be released in next version
Package Version 60:
-
:Fire()
now iterates backwards through the array to make sure disconnecting inside a connection won’t affect anything
Works, but it’s quite a bit slower now.
Hold on let me benchmark it really quickly
Ehh I mean… It’s microseconds we’re talking about here, I honestly think I’ll just keep this until someone has issues with it :V
Between GoodSignal and this it’s still microseconds. Microseconds do matter.
Also the order is inverted now.
I guess you could invert the swapback array? Is that possible?
You’d have to ìnsert at the first index which is very expensive since it requires shifting the entire array, so not worth it.