vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1  
2 -------------------------------------------------------------------
3 --***************************************************************--
4 --** All authors using this library please see the wiki: **--
5 --** http://wiki.wowace.com/index.php/Compost_Embedded_Library **--
6 --***************************************************************--
7 -------------------------------------------------------------------
8  
9 local vmajor, vminor = "compost-1", tonumber(string.sub("$Revision: 658 $", 12, -3))
10 local stubvarname = "TekLibStub"
11 local libvarname = "CompostLib"
12 local usedebug = false
13  
14  
15 local libobj = getglobal(libvarname)
16 if libobj and not libobj:NeedsUpgraded(vmajor, vminor) then return end
17  
18  
19 ---------------------------------------------------------------------------
20 -- Based off Embedded Library template
21 -- Written by Iriel <iriel@vigilance-committee.org>
22 -- Version 0.1 - 2006-03-05
23 -- Modified by Tekkub <tekkub@gmail.com>
24 ---------------------------------------------------------------------------
25  
26 local stubobj = getglobal(stubvarname)
27 if not stubobj then
28 stubobj = {}
29 setglobal(stubvarname, stubobj)
30  
31  
32 -- Instance replacement method, replace contents of old with that of new
33 function stubobj:ReplaceInstance(old, new)
34 for k,v in pairs(old) do old[k]=nil end
35 for k,v in pairs(new) do old[k]=v end
36 end
37  
38  
39 -- Get a new copy of the stub
40 function stubobj:NewStub(name)
41 local newStub = {}
42 self:ReplaceInstance(newStub, self)
43 newStub.libName = name
44 newStub.lastVersion = ''
45 newStub.versions = {}
46 return newStub
47 end
48  
49  
50 -- Get instance version
51 function stubobj:NeedsUpgraded(vmajor, vminor)
52 local versionData = self.versions[vmajor]
53 if not versionData or versionData.minor < vminor then return true end
54 end
55  
56  
57 -- Get instance version
58 function stubobj:GetInstance(version)
59 if not version then version = self.lastVersion end
60 local versionData = self.versions[version]
61 if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end
62 return versionData.instance
63 end
64  
65  
66 -- Register new instance
67 function stubobj:Register(newInstance)
68 local version,minor = newInstance:GetLibraryVersion()
69 self.lastVersion = version
70 local versionData = self.versions[version]
71 if not versionData then
72 -- This one is new!
73 versionData = {
74 instance = newInstance,
75 minor = minor,
76 old = {},
77 }
78 self.versions[version] = versionData
79 newInstance:LibActivate(self)
80 return newInstance
81 end
82 -- This is an update
83 local oldInstance = versionData.instance
84 local oldList = versionData.old
85 versionData.instance = newInstance
86 versionData.minor = minor
87 local skipCopy = newInstance:LibActivate(self, oldInstance, oldList)
88 table.insert(oldList, oldInstance)
89 if not skipCopy then
90 for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end
91 end
92 return newInstance
93 end
94 end
95  
96  
97 --------------------------------
98 -- Embedded Library --
99 --------------------------------
100  
101 if not libobj then
102 libobj = stubobj:NewStub(libvarname)
103 setglobal(libvarname, libobj)
104 end
105  
106 local lib = {}
107  
108  
109 -- Return the library's current version
110 function lib:GetLibraryVersion()
111 return vmajor, vminor
112 end
113  
114  
115 -- Activate a new instance of this library
116 function lib:LibActivate(stub, oldLib, oldList)
117 local maj, min = self:GetLibraryVersion()
118 if usedebug then print(string.format("<%s> Activating version %s - %d", libvarname, maj, min)) end
119  
120 if oldLib then
121 local omaj, omin = oldLib:GetLibraryVersion()
122 if usedebug then print(string.format("<%s> Replacing old version %s - %d", libvarname, omaj, omin)) end
123 self.var, self.k = oldLib.var, oldLib.k
124 else
125 self.k = { -- Constants go here
126 maxcache = 10, -- I think this is a good number, I'll change it later if necessary
127 }
128 self.var = { -- "Local" variables go here
129 cache = {},
130 secondarycache = {},
131 }
132  
133 -- This makes the secondary cache table a weak table, any values in it will be reclaimed
134 -- during a GC if there are no other references to them
135 setmetatable(self.var.secondarycache, {__mode = "v"})
136 end
137 -- nil return makes stub do object copy
138 end
139  
140  
141 -- Removes an empty table from the cache and returns it
142 -- or generates a new table if none available
143 function lib:GetTable()
144 if self.var.disabled then return {} end
145 if table.getn(self.var.cache) > 0 then
146 self:IncDec("totn", -1)
147 self:IncDec("numrecycled", 1)
148 return table.remove(self.var.cache)
149 elseif self:ItemsInSecondaryCache() then
150 self:IncDec("totn", -1)
151 self:IncDec("numrecycled", 1)
152 for i in pairs(self.var.secondarycache) do return table.remove(self.var.secondarycache, i) end
153 else
154 self:IncDec("numnew", 1)
155 return {}
156 end
157 end
158  
159  
160 -- Returns a table, populated with any variables passed
161 -- basically: return {a1, a2, ... a20}
162 function lib:Acquire(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
163 local t = self:GetTable()
164 return self:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
165 end
166  
167  
168 -- Acquires a table and fills it with values, hash style
169 -- basically: return {k1 = v1, k2 = v2, ... k10 = v10}
170 function lib:AcquireHash(k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
171 local t = self:GetTable()
172 return self:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
173 end
174  
175  
176 -- Erases the table passed, fills it with the args passed, and returns it
177 -- Essentially the same as doing Reclaim then Acquire, except the same table is reused
178 function lib:Recycle(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
179 t = self:Erase(t)
180 return self:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
181 end
182  
183  
184 -- Erases the table passed, fills it with the args passed, and returns it
185 -- Essentially the same as doing Reclaim then AcquireHash, except the same table is reused
186 function lib:RecycleHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
187 t = self:Erase(t)
188 return self:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
189 end
190  
191  
192 -- Returns a table to the cache
193 -- All tables referenced inside the passed table will be reclaimed also
194 -- If a depth is passed, Reclaim will call itsself recursivly
195 -- to reclaim all tables contained in t to the depth specified
196 function lib:Reclaim(t, depth)
197 if type(t) ~= "table" or self.var.disabled then return end
198  
199 if not self:ItemsInSecondaryCache() then self.var.totn = table.getn(self.var.cache) end
200  
201 if depth and depth > 0 then
202 for i in pairs(t) do
203 if type(t[i]) == "table" then self:Reclaim(t[i], depth - 1) end
204 end
205 end
206 self:Erase(t)
207 if self.k.maxcache and table.getn(self.var.cache) >= self.k.maxcache then
208 table.insert(self.var.secondarycache, t)
209 else
210 table.insert(self.var.cache, t)
211 end
212 self:IncDec("numreclaim", 1)
213 self:IncDec("totn", 1)
214 self.var.maxn = math.max(self.var.maxn or 0, self.var.totn)
215 end
216  
217  
218 -- Reclaims multiple tables, can take 10 recursive sets or 20 non-recursives,
219 -- or any combination of the two. Pass args in the following manner:
220 -- table1, depth1, tabl2, depth2, table3, table4, table5, depth5, ...
221 function lib:ReclaimMulti(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
222 if not a1 then return end
223 if type(a2) == "number" then
224 self:Reclaim(a1, a2)
225 self:ReclaimMulti(a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
226 else
227 self:Reclaim(a1)
228 self:ReclaimMulti(a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
229 end
230 end
231  
232  
233 -- Erases the table passed, nothing more nothing less :)
234 -- Tables referenced inside the passed table are NOT erased
235 function lib:Erase(t)
236 if type(t) ~= "table" then return end
237 if self.var.disabled then return {} end
238 local mem = gcinfo()
239 for i in pairs(t) do
240 t[i] = nil
241 end
242 t.reset = 1
243 t.reset = nil
244 table.setn(t, 0)
245 self:IncDec("memfreed", math.abs(gcinfo() - mem))
246 self:IncDec("numerased", 1)
247 return t
248 end
249  
250  
251 -- Fills the table passed with the args passed
252 function lib:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
253 if not t then return end
254 if a1 ~= nil then table.insert(t, a1) end
255 if a2 ~= nil then table.insert(t, a2) end
256 if a3 ~= nil then table.insert(t, a3) end
257 if a4 ~= nil then table.insert(t, a4) end
258 if a5 ~= nil then table.insert(t, a5) end
259 if a6 ~= nil then table.insert(t, a6) end
260 if a7 ~= nil then table.insert(t, a7) end
261 if a8 ~= nil then table.insert(t, a8) end
262 if a9 ~= nil then table.insert(t, a9) end
263 if a10 ~= nil then table.insert(t, a10) end
264 if a11 ~= nil then table.insert(t, a11) end
265 if a12 ~= nil then table.insert(t, a12) end
266 if a13 ~= nil then table.insert(t, a13) end
267 if a14 ~= nil then table.insert(t, a14) end
268 if a15 ~= nil then table.insert(t, a15) end
269 if a16 ~= nil then table.insert(t, a16) end
270 if a17 ~= nil then table.insert(t, a17) end
271 if a18 ~= nil then table.insert(t, a18) end
272 if a19 ~= nil then table.insert(t, a19) end
273 if a20 ~= nil then table.insert(t, a20) end
274 return t
275 end
276  
277  
278 -- Same as Populate, but takes 10 key-value pairs instead
279 function lib:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
280 if not t then return end
281 if k1 ~= nil then t[k1] = v1 end
282 if k2 ~= nil then t[k2] = v2 end
283 if k3 ~= nil then t[k3] = v3 end
284 if k4 ~= nil then t[k4] = v4 end
285 if k5 ~= nil then t[k5] = v5 end
286 if k6 ~= nil then t[k6] = v6 end
287 if k7 ~= nil then t[k7] = v7 end
288 if k8 ~= nil then t[k8] = v8 end
289 if k9 ~= nil then t[k9] = v9 end
290 if k10 ~= nil then t[k10] = v10 end
291 return t
292 end
293  
294  
295 function lib:IncDec(variable, diff)
296 self.var[variable] = (self.var[variable] or 0) + diff
297 end
298  
299  
300 function lib:ItemsInSecondaryCache()
301 for i in pairs(self.var.secondarycache) do return true end
302 end
303  
304  
305 function lib:GetSecondaryCacheSize()
306 local n = 0
307 for i in pairs(self.var.secondarycache) do n = n + 1 end
308 return n
309 end
310  
311  
312 -- Prints out statistics on table recycling
313 -- /script CompostLib:GetInstance("compost-1"):Stats()
314 function lib:Stats()
315 if self.var.disabled then ChatFrame1:AddMessage("CompostLib is disabled!")
316 else ChatFrame1:AddMessage(
317 string.format(
318 "|cff00ff00New: %d|r | |cffffff00Recycled: %d|r | |cff00ffffMain: %d|r | |cffff0000Secondary: %d|r | |cffff8800Max %d|r | |cff888888Erases: %d|r | |cffff00ffMem Saved: %d KiB|r | |cffff0088Lost to GC: %d",
319 self.var.numnew or 0,
320 self.var.numrecycled or 0,
321 table.getn(self.var.cache),
322 self:GetSecondaryCacheSize(),
323 self.var.maxn or 0,
324 (self.var.numerased or 0) - (self.var.numreclaim or 0),
325 (self.var.memfreed or 0) + 32/1024*(self.var.numrecycled or 0),
326 (self.var.numreclaim or 0) - (self.var.numrecycled or 0) - table.getn(self.var.cache)))
327 end
328 end
329  
330  
331 --------------------------------
332 -- Load this bitch! --
333 --------------------------------
334 libobj:Register(lib)