We use cookies on this site to enhance your user experience

5 min

Weak type Articles/Table|tables are the mechanism that Lua uses to tell when a reference should not prevent the reclamation of an object by the garbage collector. A weak reference is a reference to an object that is not considered by the garbage collector. If all references pointing to an object are weak, the object is collected and somehow these weak references are deleted.

Prerequisites

Learning Weak Tables require knowledge of:

  • Articles/Scope
  • Articles/Metatables

You must also understand what objects are. Articles/Table|Tables, Articles/Understanding Functions in Roblox|functions, threads, and (full) userdata values are ‘‘objects’’: Articles/Variables|variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.

Explanation

Note: all Lua objects in the global environment are ignored and will never be garbage collected, even if they aren’t used again.

Lua implements weak references as weak tables: A weak table is a Articles/Table|table where all references are weak. That means that, if a reference to an object is only held inside weak Articles/Table|tables, Lua will collect the object eventually. Tables` have keys and values and both may contain any kind of value. Under normal circumstances, the garbage collector does not collect objects that appear as keys or as values of an accessible type|table. That is, both keys and values are strong references, as they prevent the reclamation of objects to which they refer. In a weak table, keys and values may be weak. That means that there are three kinds of weak tables: tables with weak keys, tables with weak values, and fully weak tables, where both keys and values are weak. Irrespective of the table kind, when a key or a value is collected the whole entry disappears from the table.

The weakness of a Articles/Table|table is controlled by the __mode field of its Articles/Metatables|metatable. If the __mode field is a type|string containing the character ‘k’, the keys in the table are weak. If __mode contains the character v the values in the table are weak. After you use a table as a metatable, you should not change the value of its __mode field. Otherwise, the weak behavior of the tables controlled by this metatable is undefined. A table with weak keys and strong values is called an ephemeron table (Not supported until Lua 5.2).

Examples

Weak Keys

local t, key
t = {}
setmetatable(t, {__mode = "k"}) -- now a has weak keys

key = {}               -- creates first key
t[key] = 1

key = {}               -- creates second key
t[key] = 2

-- forces a garbage collection cycle
collectgarbage()       

for k, v in pairs(t) do 
	print(v) 
end

What happened there? Well, the first key is created, then made into an index in Articles/Table|table t. Then, the first key is overwritten by the second key, meaning the only reference to the first key is inside table t with a value of 1. Table t has weak keys, so when the garbage collection cycle is forced, it collects the first key because it’s only reference is a weak key; however, the second key is still in scope, automatically preventing the reclamation of the second key by the garbage collector. So, since the the first key was removed from the table, the whole pair was removed from the table, leaving only the second key and its corresponding value.

Weak Values

Here’s another example, with the value as a reference:

local t = {}
setmetatable(t, {__mode = "v"}) -- Set the values as weak

do -- Create a new scope
	-- Create a new object in this scope, 
	-- so the object can be garbage collected.
	local newValue = newproxy(true) 
	t[1] = newValue
end

collectgarbage()
print(t[1])

Alright, so we create a Articles/Table|table and give it weak values. Then we give it an object as a value (at index 1). Since the values with reference to an object are weak, the garbage collector goes ahead and collects the newValue userdata.

Now, what would happen if we commented out the line that set t's metatable?
This would be the output:

userdata: 0x153da38

The value inside t is a strong reference, so when the garbage collector made its cycle it didn’t pick up the object newValue, leaving it at index 1.

See Also