Mapping Tables Via Weak Table

I’m working on a signal system with intended behavior and API matching that of the traditional BindableEvent (while adding some typechecking support and borrowing performance enhancements from Stravant’s GoodSignal).

In this structure, the signal’s “Event” object and the “Connection” objects created from it should not expose the parent “Signal” object, but both objects will internally need to know what that parent object is in order to properly perform their logic.

To manage this, I’ve been storing references to the parent Signal in weak tables indexed by the Event and Connection objects. This has worked fine for Connections, but I’m running into problems with the Event and Signal relationship. I can’t seem to figure out how to get both objects to reference each other and still get garbage-collected once they’re out of scope.

In researching the problem a bit, I found the following pattern to achieve a solution, and while it does work in standard Lua 5.1 (with the Luau features removed), it does not work in Luau. How can this be modified to allow the references to be correctly cleaned up?

--Build a weak table to hold the objects
local link_table = setmetatable({}, {__mode = "kv"})

do
	--Create two elements and associate them with one another via the "link_table"
	local element_1 = {}
	local element_2 = {}
	link_table[element_1] = element_2
	link_table[element_2] = element_1
end

--At this point, the only references to either "element_1" or "element_2" are in the weak "link_table"

while task.wait() do	--Yield to engine to allow for garbage collection to occur.
	local count = 0
	
	for _ in pairs(link_table) do
		count += 1
	end
	
	print(count, link_table)	--Always prints 2, table still has both elements in it.
end

Yeah, that seems to be the issue. All of my tests were with a few objects at a time, leading me to think there was a memory leak. If I create a ton of signals, everything gets cleaned up properly, and there was apparently never a problem to begin with.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.