Home | History | Annotate | Download | only in xz
      1 /*
      2  * ResettableArrayCache
      3  *
      4  * Author: Lasse Collin <lasse.collin (at) 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      */
     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 
     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 
     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 
     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 
     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      */
    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