• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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