1 /* 2 * ResettableArrayCache 3 * 4 * Author: Lasse Collin <lasse.collin@tukaani.org> 5 * 6 * This file has been put into the public domain. 7 * You can do whatever you want with this file. 8 */ 9 10 package org.tukaani.xz; 11 12 import java.util.ArrayList; 13 import java.util.List; 14 15 /** 16 * An ArrayCache wrapper that remembers what has been allocated 17 * and allows returning all allocations to the underlying cache at once. 18 * 19 * @since 1.7 20 */ 21 public class ResettableArrayCache extends ArrayCache { 22 private final ArrayCache arrayCache; 23 24 // Lists of arrays that have been allocated from the arrayCache. 25 private final List<byte[]> byteArrays; 26 private final List<int[]> intArrays; 27 28 /** 29 * Creates a new ResettableArrayCache based on the given ArrayCache. 30 */ ResettableArrayCache(ArrayCache arrayCache)31 public ResettableArrayCache(ArrayCache arrayCache) { 32 this.arrayCache = arrayCache; 33 34 // Treat the dummy cache as a special case since it's a common case. 35 // With it we don't need to put the arrays back to the cache and 36 // thus we don't need to remember what has been allocated. 37 if (arrayCache == ArrayCache.getDummyCache()) { 38 byteArrays = null; 39 intArrays = null; 40 } else { 41 byteArrays = new ArrayList<byte[]>(); 42 intArrays = new ArrayList<int[]>(); 43 } 44 } 45 getByteArray(int size, boolean fillWithZeros)46 public byte[] getByteArray(int size, boolean fillWithZeros) { 47 byte[] array = arrayCache.getByteArray(size, fillWithZeros); 48 49 if (byteArrays != null) { 50 synchronized(byteArrays) { 51 byteArrays.add(array); 52 } 53 } 54 55 return array; 56 } 57 putArray(byte[] array)58 public void putArray(byte[] array) { 59 if (byteArrays != null) { 60 // The array is more likely to be near the end of the list so 61 // start the search from the end. 62 synchronized(byteArrays) { 63 int i = byteArrays.lastIndexOf(array); 64 if (i != -1) 65 byteArrays.remove(i); 66 } 67 68 arrayCache.putArray(array); 69 } 70 } 71 getIntArray(int size, boolean fillWithZeros)72 public int[] getIntArray(int size, boolean fillWithZeros) { 73 int[] array = arrayCache.getIntArray(size, fillWithZeros); 74 75 if (intArrays != null) { 76 synchronized(intArrays) { 77 intArrays.add(array); 78 } 79 } 80 81 return array; 82 } 83 putArray(int[] array)84 public void putArray(int[] array) { 85 if (intArrays != null) { 86 synchronized(intArrays) { 87 int i = intArrays.lastIndexOf(array); 88 if (i != -1) 89 intArrays.remove(i); 90 } 91 92 arrayCache.putArray(array); 93 } 94 } 95 96 /** 97 * Puts all allocated arrays back to the underlying ArrayCache 98 * that haven't already been put there with a call to 99 * {@code putArray}. 100 */ reset()101 public void reset() { 102 if (byteArrays != null) { 103 // Put the arrays to the cache in reverse order: the array that 104 // was allocated first is returned last. 105 synchronized(byteArrays) { 106 for (int i = byteArrays.size() - 1; i >= 0; --i) 107 arrayCache.putArray(byteArrays.get(i)); 108 109 byteArrays.clear(); 110 } 111 112 synchronized(intArrays) { 113 for (int i = intArrays.size() - 1; i >= 0; --i) 114 arrayCache.putArray(intArrays.get(i)); 115 116 intArrays.clear(); 117 } 118 } 119 } 120 } 121