-
Notifications
You must be signed in to change notification settings - Fork 237
/
Copy pathtrashbag.lua
73 lines (57 loc) · 2.68 KB
/
trashbag.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
-- TrashBag is a class to help manage objects that need destruction. You add objects to it with Add().
-- When TrashBag:Destroy() is called, it calls Destroy() in turn on all its contained objects.
--
-- If an object in a TrashBag is destroyed through other means, it automatically disappears from the TrashBag.
-- This doesn't necessarily happen instantly, so it's possible in this case that Destroy() will be called twice.
-- So Destroy() should always be idempotent.
-- The Trashbag is a global entity. You can use these upvalued versions to improve
-- the performance of functions using the trashbag. According to the function-scope
-- benchmark the performance is increased by about 10%.
-- START COPY HERE --
-- Upvalued for performance (function-scope benchmark)
-- local TrashBag = TrashBag
-- local TrashAdd = TrashBag.Add
-- local TrashDestroy = TrashBag.Destroy
-- END COPY HERE --
TrashBag = Class {
-- Tell the garbage collector that we're a weak table for our values. If an element is ready to be collected
-- then we're not a reason for it to remain alive. E.g., we don't care if it got cleaned up earlier.
-- http://lua-users.org/wiki/GarbageCollectionTutorial
-- http://lua-users.org/wiki/WeakTablesTutorial
__mode = 'v',
-- Keep track of the number of elements in the trash bag
Next = 1,
--- Add an entity to the trash bag.
Add = function(self, entity)
-- -- Uncomment for performance testing
-- if entity == nil then
-- WARN("Attempted to add a nil to a TrashBag: " .. repr(debug.getinfo(2)))
-- return
-- end
-- -- Uncomment for performance testing
-- if not entity.Destroy then
-- WARN("Attempted to add an entity with no Destroy() method to a TrashBag: " .. repr(debug.getinfo(2)))
-- return
-- end
-- Keeping track of separate counter for performance (table-loops benchmark). The
-- counter is updated _after_ the table has been set, this is faster because the table
-- operation depends on the counter value and doesn't have to wait for it in this case.
self[self.Next] = entity
self.Next = self.Next + 1
end,
--- Destroy all (remaining) entities in the trash bag.
Destroy = function(self)
-- -- Uncomment for performance testing
-- if not self then
-- WARN("Attempted to trash non-existing trash bag: " .. repr(debug.getinfo(2)))
-- return
-- end
-- Check if values are still relevant
for k = 1, self.Next - 1 do
if self[k] then
self[k]:Destroy()
self[k] = nil
end
end
end
}