/* * ResettableArrayCache * * Author: Lasse Collin * * This file has been put into the public domain. * You can do whatever you want with this file. */ package org.tukaani.xz; import java.util.ArrayList; import java.util.List; /** * An ArrayCache wrapper that remembers what has been allocated * and allows returning all allocations to the underlying cache at once. * * @since 1.7 */ public class ResettableArrayCache extends ArrayCache { private final ArrayCache arrayCache; // Lists of arrays that have been allocated from the arrayCache. private final List byteArrays; private final List intArrays; /** * Creates a new ResettableArrayCache based on the given ArrayCache. */ public ResettableArrayCache(ArrayCache arrayCache) { this.arrayCache = arrayCache; // Treat the dummy cache as a special case since it's a common case. // With it we don't need to put the arrays back to the cache and // thus we don't need to remember what has been allocated. if (arrayCache == ArrayCache.getDummyCache()) { byteArrays = null; intArrays = null; } else { byteArrays = new ArrayList(); intArrays = new ArrayList(); } } public byte[] getByteArray(int size, boolean fillWithZeros) { byte[] array = arrayCache.getByteArray(size, fillWithZeros); if (byteArrays != null) { synchronized(byteArrays) { byteArrays.add(array); } } return array; } public void putArray(byte[] array) { if (byteArrays != null) { // The array is more likely to be near the end of the list so // start the search from the end. synchronized(byteArrays) { int i = byteArrays.lastIndexOf(array); if (i != -1) byteArrays.remove(i); } arrayCache.putArray(array); } } public int[] getIntArray(int size, boolean fillWithZeros) { int[] array = arrayCache.getIntArray(size, fillWithZeros); if (intArrays != null) { synchronized(intArrays) { intArrays.add(array); } } return array; } public void putArray(int[] array) { if (intArrays != null) { synchronized(intArrays) { int i = intArrays.lastIndexOf(array); if (i != -1) intArrays.remove(i); } arrayCache.putArray(array); } } /** * Puts all allocated arrays back to the underlying ArrayCache * that haven't already been put there with a call to * {@code putArray}. */ public void reset() { if (byteArrays != null) { // Put the arrays to the cache in reverse order: the array that // was allocated first is returned last. synchronized(byteArrays) { for (int i = byteArrays.size() - 1; i >= 0; --i) arrayCache.putArray(byteArrays.get(i)); byteArrays.clear(); } synchronized(intArrays) { for (int i = intArrays.size() - 1; i >= 0; --i) arrayCache.putArray(intArrays.get(i)); intArrays.clear(); } } } }