blob: 2f89c1d9919ff636ee213925f01dea192469fe6e [file] [log] [blame]
/*
* ResettableArrayCache
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* 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<byte[]> byteArrays;
private final List<int[]> 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<byte[]>();
intArrays = new ArrayList<int[]>();
}
}
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();
}
}
}
}