38 * This class is a renderer context dedicated to a single thread |
38 * This class is a renderer context dedicated to a single thread |
39 */ |
39 */ |
40 final class RendererContext extends ReentrantContext implements MarlinConst { |
40 final class RendererContext extends ReentrantContext implements MarlinConst { |
41 |
41 |
42 // RendererContext creation counter |
42 // RendererContext creation counter |
43 private static final AtomicInteger contextCount = new AtomicInteger(1); |
43 private static final AtomicInteger CTX_COUNT = new AtomicInteger(1); |
44 // RendererContext statistics |
44 // RendererContext statistics |
45 static final RendererStats stats = (doStats || doMonitors) |
45 final RendererStats stats = (DO_STATS || DO_MONITORS) |
46 ? RendererStats.getInstance(): null; |
46 ? RendererStats.getInstance(): null; |
47 |
47 |
48 private static final boolean USE_CACHE_HARD_REF = doStats |
48 private static final boolean USE_CACHE_HARD_REF = DO_STATS |
49 || (MarlinRenderingEngine.REF_TYPE == ReentrantContextProvider.REF_WEAK); |
49 || (MarlinRenderingEngine.REF_TYPE == ReentrantContextProvider.REF_WEAK); |
50 |
50 |
51 /** |
51 /** |
52 * Create a new renderer context |
52 * Create a new renderer context |
53 * |
53 * |
54 * @return new RendererContext instance |
54 * @return new RendererContext instance |
55 */ |
55 */ |
56 static RendererContext createContext() { |
56 static RendererContext createContext() { |
57 final RendererContext newCtx = new RendererContext("ctx" |
57 final RendererContext newCtx = new RendererContext("ctx" |
58 + Integer.toString(contextCount.getAndIncrement())); |
58 + Integer.toString(CTX_COUNT.getAndIncrement())); |
59 |
59 |
60 if (RendererContext.stats != null) { |
60 if (DO_STATS || DO_MONITORS) { |
61 RendererContext.stats.allContexts.add(newCtx); |
61 RendererStats.ALL_CONTEXTS.add(newCtx); |
62 } |
62 } |
63 return newCtx; |
63 return newCtx; |
64 } |
64 } |
65 |
65 |
66 // context name (debugging purposes) |
66 // context name (debugging purposes) |
160 holder = (refArrayCaches != null) |
160 holder = (refArrayCaches != null) |
161 ? refArrayCaches.get() |
161 ? refArrayCaches.get() |
162 : null; |
162 : null; |
163 // create a new ArrayCachesHolder if none is available |
163 // create a new ArrayCachesHolder if none is available |
164 if (holder == null) { |
164 if (holder == null) { |
165 if (logCreateContext) { |
165 if (LOG_CREATE_CONTEXT) { |
166 MarlinUtils.logInfo("new ArrayCachesHolder for " |
166 MarlinUtils.logInfo("new ArrayCachesHolder for " |
167 + "RendererContext = " + name); |
167 + "RendererContext = " + name); |
168 } |
168 } |
169 |
169 |
170 holder = new ArrayCachesHolder(); |
170 holder = new ArrayCachesHolder(); |
190 byte[] getDirtyByteArray(final int length) { |
190 byte[] getDirtyByteArray(final int length) { |
191 if (length <= MAX_DIRTY_BYTE_ARRAY_SIZE) { |
191 if (length <= MAX_DIRTY_BYTE_ARRAY_SIZE) { |
192 return getDirtyByteArrayCache(length).getArray(); |
192 return getDirtyByteArrayCache(length).getArray(); |
193 } |
193 } |
194 |
194 |
195 if (doStats) { |
195 if (DO_STATS) { |
196 incOversize(); |
196 incOversize(); |
197 } |
197 } |
198 |
198 |
199 if (doLogOverSize) { |
199 if (DO_LOG_OVERSIZE) { |
200 logInfo("getDirtyByteArray[oversize]: length=\t" + length); |
200 logInfo("getDirtyByteArray[oversize]: length=\t" + length); |
201 } |
201 } |
202 |
202 |
203 return new byte[length]; |
203 return new byte[length]; |
204 } |
204 } |
214 |
214 |
215 byte[] widenDirtyByteArray(final byte[] in, |
215 byte[] widenDirtyByteArray(final byte[] in, |
216 final int usedSize, final int needSize) |
216 final int usedSize, final int needSize) |
217 { |
217 { |
218 final int length = in.length; |
218 final int length = in.length; |
219 if (doChecks && length >= needSize) { |
219 if (DO_CHECKS && length >= needSize) { |
220 return in; |
220 return in; |
221 } |
221 } |
222 if (doStats) { |
222 if (DO_STATS) { |
223 incResizeDirtyByte(); |
223 incResizeDirtyByte(); |
224 } |
224 } |
225 |
225 |
226 // maybe change bucket: |
226 // maybe change bucket: |
227 // ensure getNewSize() > newSize: |
227 // ensure getNewSize() > newSize: |
231 |
231 |
232 // maybe return current array: |
232 // maybe return current array: |
233 // NO clean-up of array data = DIRTY ARRAY |
233 // NO clean-up of array data = DIRTY ARRAY |
234 putDirtyByteArray(in); |
234 putDirtyByteArray(in); |
235 |
235 |
236 if (doLogWidenArray) { |
236 if (DO_LOG_WIDEN_ARRAY) { |
237 logInfo("widenDirtyByteArray[" + res.length + "]: usedSize=\t" |
237 logInfo("widenDirtyByteArray[" + res.length + "]: usedSize=\t" |
238 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
238 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
239 + needSize); |
239 + needSize); |
240 } |
240 } |
241 return res; |
241 return res; |
250 int[] getIntArray(final int length) { |
250 int[] getIntArray(final int length) { |
251 if (length <= MAX_ARRAY_SIZE) { |
251 if (length <= MAX_ARRAY_SIZE) { |
252 return getIntArrayCache(length).getArray(); |
252 return getIntArrayCache(length).getArray(); |
253 } |
253 } |
254 |
254 |
255 if (doStats) { |
255 if (DO_STATS) { |
256 incOversize(); |
256 incOversize(); |
257 } |
257 } |
258 |
258 |
259 if (doLogOverSize) { |
259 if (DO_LOG_OVERSIZE) { |
260 logInfo("getIntArray[oversize]: length=\t" + length); |
260 logInfo("getIntArray[oversize]: length=\t" + length); |
261 } |
261 } |
262 |
262 |
263 return new int[length]; |
263 return new int[length]; |
264 } |
264 } |
266 // unused |
266 // unused |
267 int[] widenIntArray(final int[] in, final int usedSize, |
267 int[] widenIntArray(final int[] in, final int usedSize, |
268 final int needSize, final int clearTo) |
268 final int needSize, final int clearTo) |
269 { |
269 { |
270 final int length = in.length; |
270 final int length = in.length; |
271 if (doChecks && length >= needSize) { |
271 if (DO_CHECKS && length >= needSize) { |
272 return in; |
272 return in; |
273 } |
273 } |
274 if (doStats) { |
274 if (DO_STATS) { |
275 incResizeInt(); |
275 incResizeInt(); |
276 } |
276 } |
277 |
277 |
278 // maybe change bucket: |
278 // maybe change bucket: |
279 // ensure getNewSize() > newSize: |
279 // ensure getNewSize() > newSize: |
282 System.arraycopy(in, 0, res, 0, usedSize); // copy only used elements |
282 System.arraycopy(in, 0, res, 0, usedSize); // copy only used elements |
283 |
283 |
284 // maybe return current array: |
284 // maybe return current array: |
285 putIntArray(in, 0, clearTo); // ensure all array is cleared (grow-reduce algo) |
285 putIntArray(in, 0, clearTo); // ensure all array is cleared (grow-reduce algo) |
286 |
286 |
287 if (doLogWidenArray) { |
287 if (DO_LOG_WIDEN_ARRAY) { |
288 logInfo("widenIntArray[" + res.length + "]: usedSize=\t" |
288 logInfo("widenIntArray[" + res.length + "]: usedSize=\t" |
289 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
289 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
290 + needSize); |
290 + needSize); |
291 } |
291 } |
292 return res; |
292 return res; |
312 int[] getDirtyIntArray(final int length) { |
312 int[] getDirtyIntArray(final int length) { |
313 if (length <= MAX_ARRAY_SIZE) { |
313 if (length <= MAX_ARRAY_SIZE) { |
314 return getDirtyIntArrayCache(length).getArray(); |
314 return getDirtyIntArrayCache(length).getArray(); |
315 } |
315 } |
316 |
316 |
317 if (doStats) { |
317 if (DO_STATS) { |
318 incOversize(); |
318 incOversize(); |
319 } |
319 } |
320 |
320 |
321 if (doLogOverSize) { |
321 if (DO_LOG_OVERSIZE) { |
322 logInfo("getDirtyIntArray[oversize]: length=\t" + length); |
322 logInfo("getDirtyIntArray[oversize]: length=\t" + length); |
323 } |
323 } |
324 |
324 |
325 return new int[length]; |
325 return new int[length]; |
326 } |
326 } |
327 |
327 |
328 int[] widenDirtyIntArray(final int[] in, |
328 int[] widenDirtyIntArray(final int[] in, |
329 final int usedSize, final int needSize) |
329 final int usedSize, final int needSize) |
330 { |
330 { |
331 final int length = in.length; |
331 final int length = in.length; |
332 if (doChecks && length >= needSize) { |
332 if (DO_CHECKS && length >= needSize) { |
333 return in; |
333 return in; |
334 } |
334 } |
335 if (doStats) { |
335 if (DO_STATS) { |
336 incResizeDirtyInt(); |
336 incResizeDirtyInt(); |
337 } |
337 } |
338 |
338 |
339 // maybe change bucket: |
339 // maybe change bucket: |
340 // ensure getNewSize() > newSize: |
340 // ensure getNewSize() > newSize: |
344 |
344 |
345 // maybe return current array: |
345 // maybe return current array: |
346 // NO clean-up of array data = DIRTY ARRAY |
346 // NO clean-up of array data = DIRTY ARRAY |
347 putDirtyIntArray(in); |
347 putDirtyIntArray(in); |
348 |
348 |
349 if (doLogWidenArray) { |
349 if (DO_LOG_WIDEN_ARRAY) { |
350 logInfo("widenDirtyIntArray[" + res.length + "]: usedSize=\t" |
350 logInfo("widenDirtyIntArray[" + res.length + "]: usedSize=\t" |
351 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
351 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
352 + needSize); |
352 + needSize); |
353 } |
353 } |
354 return res; |
354 return res; |
372 float[] getDirtyFloatArray(final int length) { |
372 float[] getDirtyFloatArray(final int length) { |
373 if (length <= MAX_ARRAY_SIZE) { |
373 if (length <= MAX_ARRAY_SIZE) { |
374 return getDirtyFloatArrayCache(length).getArray(); |
374 return getDirtyFloatArrayCache(length).getArray(); |
375 } |
375 } |
376 |
376 |
377 if (doStats) { |
377 if (DO_STATS) { |
378 incOversize(); |
378 incOversize(); |
379 } |
379 } |
380 |
380 |
381 if (doLogOverSize) { |
381 if (DO_LOG_OVERSIZE) { |
382 logInfo("getDirtyFloatArray[oversize]: length=\t" + length); |
382 logInfo("getDirtyFloatArray[oversize]: length=\t" + length); |
383 } |
383 } |
384 |
384 |
385 return new float[length]; |
385 return new float[length]; |
386 } |
386 } |
387 |
387 |
388 float[] widenDirtyFloatArray(final float[] in, |
388 float[] widenDirtyFloatArray(final float[] in, |
389 final int usedSize, final int needSize) |
389 final int usedSize, final int needSize) |
390 { |
390 { |
391 final int length = in.length; |
391 final int length = in.length; |
392 if (doChecks && length >= needSize) { |
392 if (DO_CHECKS && length >= needSize) { |
393 return in; |
393 return in; |
394 } |
394 } |
395 if (doStats) { |
395 if (DO_STATS) { |
396 incResizeDirtyFloat(); |
396 incResizeDirtyFloat(); |
397 } |
397 } |
398 |
398 |
399 // maybe change bucket: |
399 // maybe change bucket: |
400 // ensure getNewSize() > newSize: |
400 // ensure getNewSize() > newSize: |
404 |
404 |
405 // maybe return current array: |
405 // maybe return current array: |
406 // NO clean-up of array data = DIRTY ARRAY |
406 // NO clean-up of array data = DIRTY ARRAY |
407 putDirtyFloatArray(in); |
407 putDirtyFloatArray(in); |
408 |
408 |
409 if (doLogWidenArray) { |
409 if (DO_LOG_WIDEN_ARRAY) { |
410 logInfo("widenDirtyFloatArray[" + res.length + "]: usedSize=\t" |
410 logInfo("widenDirtyFloatArray[" + res.length + "]: usedSize=\t" |
411 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
411 + usedSize + "\tlength=\t" + length + "\tneeded length=\t" |
412 + needSize); |
412 + needSize); |
413 } |
413 } |
414 return res; |
414 return res; |