vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
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