vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --------------------------------------------------------------------------- |
2 | -- Embedded Library Registration Stub |
||
3 | -- Written by Iriel <iriel@vigilance-committee.org> |
||
4 | -- Version 0.1 - 2006-03-05 |
||
5 | -- Modified by Tekkub <tekkub@gmail.com> |
||
6 | --------------------------------------------------------------------------- |
||
7 | -- YOU DON'T NEED TO TOUCH ANYTHING IN THIS BLOCK OF CODE |
||
8 | --------------------------------------------------------------------------- |
||
9 | |||
10 | if not EmbedLibStub then |
||
11 | EmbedLibStub = {} |
||
12 | |||
13 | |||
14 | -- Instance replacement method, replace contents of old with that of new |
||
15 | function EmbedLibStub:ReplaceInstance(old, new) |
||
16 | for k,v in pairs(old) do old[k]=nil end |
||
17 | for k,v in pairs(new) do old[k]=v end |
||
18 | end |
||
19 | |||
20 | |||
21 | -- Get a new copy of the stub |
||
22 | function EmbedLibStub:NewStub(name) |
||
23 | local newStub = {} |
||
24 | self:ReplaceInstance(newStub, self) |
||
25 | newStub.libName = name |
||
26 | newStub.lastVersion = '' |
||
27 | newStub.versions = {} |
||
28 | return newStub |
||
29 | end |
||
30 | |||
31 | |||
32 | -- Get instance version |
||
33 | function EmbedLibStub:NeedsUpgraded(vmajor, vminor) |
||
34 | local versionData = self.versions[vmajor] |
||
35 | if not versionData or versionData.minor < vminor then return true end |
||
36 | end |
||
37 | |||
38 | |||
39 | -- Get instance version |
||
40 | function EmbedLibStub:GetInstance(version) |
||
41 | if not version then version = self.lastVersion end |
||
42 | local versionData = self.versions[version] |
||
43 | if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end |
||
44 | return versionData.instance |
||
45 | end |
||
46 | |||
47 | |||
48 | -- Register new instance |
||
49 | function EmbedLibStub:Register(newInstance) |
||
50 | local version,minor = newInstance:GetLibraryVersion() |
||
51 | self.lastVersion = version |
||
52 | local versionData = self.versions[version] |
||
53 | if not versionData then |
||
54 | -- This one is new! |
||
55 | versionData = { |
||
56 | instance = newInstance, |
||
57 | minor = minor, |
||
58 | old = {}, |
||
59 | } |
||
60 | self.versions[version] = versionData |
||
61 | newInstance:LibActivate(self) |
||
62 | return newInstance |
||
63 | end |
||
64 | -- This is an update |
||
65 | local oldInstance = versionData.instance |
||
66 | local oldList = versionData.old |
||
67 | versionData.instance = newInstance |
||
68 | versionData.minor = minor |
||
69 | local skipCopy = newInstance:LibActivate(self, oldInstance, oldList) |
||
70 | table.insert(oldList, oldInstance) |
||
71 | if not skipCopy then |
||
72 | for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end |
||
73 | end |
||
74 | return newInstance |
||
75 | end |
||
76 | end |
||
77 | |||
78 | |||
79 | |||
80 | ---------------------------------- |
||
81 | -- Library Definition -- |
||
82 | ---------------------------------- |
||
83 | |||
84 | local vmajor, vminor = "compost-1", 1 |
||
85 | local libvarname = "CompostLib" |
||
86 | local usedebug = false |
||
87 | |||
88 | |||
89 | --------------------------------------------------------------------------- |
||
90 | -- This code is the Library's management code |
||
91 | -- You don't need to change anything here |
||
92 | --------------------------------------------------------------------------- |
||
93 | |||
94 | local libobj = getglobal(libvarname) |
||
95 | if not libobj then |
||
96 | libobj = EmbedLibStub:NewStub(libvarname) |
||
97 | setglobal(libvarname, libobj) |
||
98 | end |
||
99 | |||
100 | |||
101 | if libobj:NeedsUpgraded(vmajor, vminor) then |
||
102 | |||
103 | local lib = {} |
||
104 | |||
105 | |||
106 | -- Return the library's current version |
||
107 | function lib:GetLibraryVersion() return vmajor, vminor end |
||
108 | |||
109 | |||
110 | -- Activate a new instance of this library |
||
111 | function lib:LibActivate(stub, oldLib, oldList) |
||
112 | local maj, min = self:GetLibraryVersion() |
||
113 | if usedebug then print(string.format("<%s> Activating version %s - %d", libvarname, maj, min)) end |
||
114 | |||
115 | if oldLib then |
||
116 | local omaj, omin = oldLib:GetLibraryVersion() |
||
117 | if usedebug then print(string.format("<%s> Replacing old version %s - %d", libvarname, omaj, omin)) end |
||
118 | |||
119 | self.var, self.k = oldLib.var, oldLib.k |
||
120 | else |
||
121 | self.k = { -- Constants go here |
||
122 | maxcache = 10, -- I think this is a good number, I'll change it later if necessary |
||
123 | } |
||
124 | self.var = { -- "Local" variables go here |
||
125 | cache = {}, |
||
126 | secondarycache = {}, |
||
127 | } |
||
128 | |||
129 | -- This makes the secondary cache table a weak table, any values in it will be reclaimed |
||
130 | -- during a GC if there are no other references to them |
||
131 | setmetatable(self.var.secondarycache, {__mode = "v"}) |
||
132 | end |
||
133 | -- nil return makes stub do object copy |
||
134 | end |
||
135 | |||
136 | |||
137 | -- Removes an empty table from the cache and returns it |
||
138 | -- or generates a new table if none available |
||
139 | function lib:Acquire() |
||
140 | if self.var.disabled then return {} end |
||
141 | if table.getn(self.var.cache) > 0 then |
||
142 | self:IncDec("totn", -1) |
||
143 | self:IncDec("numr", 1) |
||
144 | local t = self.var.cache[1] |
||
145 | table.remove(self.var.cache, 1) |
||
146 | return t |
||
147 | elseif self:ItemsInSecondaryCache() then |
||
148 | self:IncDec("totn", -1) |
||
149 | self:IncDec("numr", 1) |
||
150 | for i in pairs(self.var.secondarycache) do |
||
151 | local t = self.var.secondarycache[i] |
||
152 | table.remove(self.var.secondarycache, i) |
||
153 | return t |
||
154 | end |
||
155 | else |
||
156 | self:IncDec("numn", 1) |
||
157 | return {} |
||
158 | end |
||
159 | end |
||
160 | |||
161 | |||
162 | -- Returns a table to the cache |
||
163 | -- All tables referenced inside the passed table will be reclaimed also |
||
164 | -- If depth is passed any tables referenced in t will also be reclaimed ***USE THIS CAREFULLY*** |
||
165 | function lib:Reclaim(t, depth) |
||
166 | if type(t) ~= "table" or self.var.disabled then return end |
||
167 | |||
168 | if not self:ItemsInSecondaryCache() then self.var.totn = table.getn(self.var.cache) end |
||
169 | |||
170 | if depth and depth > 0 then |
||
171 | for i in pairs(t) do |
||
172 | if type(t[i]) == "table" then self:Reclaim(t[i], depth - 1) end |
||
173 | end |
||
174 | end |
||
175 | self:Erase(t) |
||
176 | if self.var.maxcache and table.getn(self.var.cache) >= self.var.maxcache then |
||
177 | table.insert(self.var.secondarycache, t) |
||
178 | else |
||
179 | table.insert(self.var.cache, t) |
||
180 | end |
||
181 | self:IncDec("totn", 1) |
||
182 | self.var.maxn = math.max(self.var.maxn or 0, self.var.totn) |
||
183 | end |
||
184 | |||
185 | |||
186 | -- Erases the table passed, nothing more nothing less :) |
||
187 | -- Tables referenced inside the passed table are NOT erased |
||
188 | function lib:Erase(t) |
||
189 | if type(t) ~= "table" then return end |
||
190 | if self.var.disabled then return {} end |
||
191 | local mem = gcinfo() |
||
192 | for i in pairs(t) do |
||
193 | t[i] = nil |
||
194 | end |
||
195 | t.reset = 1 |
||
196 | t.reset = nil |
||
197 | table.setn(t, 0) |
||
198 | self:IncDec("memf", math.abs(gcinfo() - mem)) |
||
199 | self:IncDec("nume", 1) |
||
200 | return t |
||
201 | end |
||
202 | |||
203 | |||
204 | function lib:IncDec(variable, diff) |
||
205 | self.var[variable] = (self.var[variable] or 0) + diff |
||
206 | end |
||
207 | |||
208 | |||
209 | function lib:ItemsInSecondaryCache() |
||
210 | for i in pairs(self.var.secondarycache) do return true end |
||
211 | end |
||
212 | |||
213 | |||
214 | function lib:GetSecondaryCacheSize() |
||
215 | local n = 0 |
||
216 | for i in pairs(self.var.secondarycache) do n = n + 1 end |
||
217 | return n |
||
218 | end |
||
219 | |||
220 | |||
221 | -- Prints out statistics on table recycling |
||
222 | -- /script CompostLib:GetInstance("compost-1"):Stats() |
||
223 | function lib:Stats() |
||
224 | if self.var.disabled then ChatFrame1:AddMessage("CompostLib is disabled!") |
||
225 | else ChatFrame1:AddMessage( |
||
226 | string.format( |
||
227 | "|cff00ff00New: %d|r | |cffffff00Recycled: %d|r | |cff00ffffSaved: %d|r | |cffff0000Secondary: %d|r | |cffff8800Max %d|r | |cff888888Erases: %d|r | |cffff00ffMem Freed: %d KiB", |
||
228 | self.var.numn or 0, self.var.numr or 0, table.getn(self.var.cache), self:GetSecondaryCacheSize(), self.var.maxn or 0, |
||
229 | (self.var.nume or 0) - (self.var.numr or 0) - table.getn(self.var.cache) - self:GetSecondaryCacheSize(), |
||
230 | (self.var.memf or 0) + 32/1024*(self.var.numr or 0))) |
||
231 | end |
||
232 | end |
||
233 | |||
234 | |||
235 | -------------------------------- |
||
236 | -- Load this bitch! -- |
||
237 | -------------------------------- |
||
238 | libobj:Register(lib) |
||
239 | end |