• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ArrayCache
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 /**
13  * Caches large arrays for reuse (base class and a dummy cache implementation).
14  * <p>
15  * When compressing or decompressing many (very) small files in a row, the
16  * time spent in construction of new compressor or decompressor objects
17  * can be longer than the time spent in actual compression or decompression.
18  * A large part of this initialization overhead comes from allocation and
19  * garbage collection of large arrays.
20  * <p>
21  * The {@code ArrayCache} API provides a way to cache large array allocations
22  * for reuse. It can give a major performance improvement when compressing or
23  * decompressing many tiny files. If you are only (de)compressing one or two
24  * files or the files a very big, array caching won't improve anything,
25  * although it won't make anything slower either.
26  * <p>
27  * <b>Important: The users of ArrayCache don't return the allocated arrays
28  * back to the cache in all situations.</b>
29  * This a reason why it's called a cache instead of a pool.
30  * If it is important to be able to return every array back to a cache,
31  * {@link ResettableArrayCache} can be useful.
32  * <p>
33  * In compressors (OutputStreams) the arrays are returned to the cache
34  * when a call to {@code finish()} or {@code close()} returns
35  * successfully (no exceptions are thrown).
36  * <p>
37  * In decompressors (InputStreams) the arrays are returned to the cache when
38  * the decompression is successfully finished ({@code read} returns {@code -1})
39  * or {@code close()} or {@code close(boolean)} is called. This is true even
40  * if closing throws an exception.
41  * <p>
42  * Raw decompressors don't support {@code close(boolean)}. With raw
43  * decompressors, if one wants to put the arrays back to the cache without
44  * closing the underlying {@code InputStream}, one can wrap the
45  * {@code InputStream} into {@link CloseIgnoringInputStream} when creating
46  * the decompressor instance. Then one can use {@code close()}.
47  * <p>
48  * Different cache implementations can be extended from this base class.
49  * All cache implementations must be thread safe.
50  * <p>
51  * This class also works as a dummy cache that simply calls {@code new}
52  * to allocate new arrays and doesn't try to cache anything. A statically
53  * allocated dummy cache is available via {@link #getDummyCache()}.
54  * <p>
55  * If no {@code ArrayCache} is specified when constructing a compressor or
56  * decompressor, the default {@code ArrayCache} implementation is used.
57  * See {@link #getDefaultCache()} and {@link #setDefaultCache(ArrayCache)}.
58  * <p>
59  * This is a class instead of an interface because it's possible that in the
60  * future we may want to cache other array types too. New methods can be
61  * added to this class without breaking existing cache implementations.
62  *
63  * @since 1.7
64  *
65  * @see BasicArrayCache
66  */
67 public class ArrayCache {
68     /**
69      * Global dummy cache instance that is returned by {@code getDummyCache()}.
70      */
71     private static final ArrayCache dummyCache = new ArrayCache();
72 
73     /**
74      * Global default {@code ArrayCache} that is used when no other cache has
75      * been specified.
76      */
77     private static volatile ArrayCache defaultCache = dummyCache;
78 
79     /**
80      * Returns a statically-allocated {@code ArrayCache} instance.
81      * It can be shared by all code that needs a dummy cache.
82      */
getDummyCache()83     public static ArrayCache getDummyCache() {
84         return dummyCache;
85     }
86 
87     /**
88      * Gets the default {@code ArrayCache} instance.
89      * This is a global cache that is used when the application
90      * specifies nothing else. The default is a dummy cache
91      * (see {@link #getDummyCache()}).
92      */
getDefaultCache()93     public static ArrayCache getDefaultCache() {
94         // It's volatile so no need for synchronization.
95         return defaultCache;
96     }
97 
98     /**
99      * Sets the default {@code ArrayCache} instance.
100      * Use with care. Other libraries using this package probably shouldn't
101      * call this function as libraries cannot know if there are other users
102      * of the xz package in the same application.
103      */
setDefaultCache(ArrayCache arrayCache)104     public static void setDefaultCache(ArrayCache arrayCache) {
105         if (arrayCache == null)
106             throw new NullPointerException();
107 
108         // It's volatile so no need for synchronization.
109         defaultCache = arrayCache;
110     }
111 
112     /**
113      * Creates a new {@code ArrayCache} that does no caching
114      * (a dummy cache). If you need a dummy cache, you may want to call
115      * {@link #getDummyCache()} instead.
116      */
ArrayCache()117     public ArrayCache() {}
118 
119     /**
120      * Allocates a new byte array.
121      * <p>
122      * This implementation simply returns {@code new byte[size]}.
123      *
124      * @param   size            the minimum size of the array to allocate;
125      *                          an implementation may return an array that
126      *                          is larger than the given {@code size}
127      *
128      * @param   fillWithZeros   if true, the caller expects that the first
129      *                          {@code size} elements in the array are zero;
130      *                          if false, the array contents can be anything,
131      *                          which speeds things up when reusing a cached
132      *                          array
133      */
getByteArray(int size, boolean fillWithZeros)134     public byte[] getByteArray(int size, boolean fillWithZeros) {
135         return new byte[size];
136     }
137 
138     /**
139      * Puts the given byte array to the cache. The caller must no longer
140      * use the array.
141      * <p>
142      * This implementation does nothing.
143      */
putArray(byte[] array)144     public void putArray(byte[] array) {}
145 
146     /**
147      * Allocates a new int array.
148      * <p>
149      * This implementation simply returns {@code new int[size]}.
150      *
151      * @param   size            the minimum size of the array to allocate;
152      *                          an implementation may return an array that
153      *                          is larger than the given {@code size}
154      *
155      * @param   fillWithZeros   if true, the caller expects that the first
156      *                          {@code size} elements in the array are zero;
157      *                          if false, the array contents can be anything,
158      *                          which speeds things up when reusing a cached
159      *                          array
160      */
getIntArray(int size, boolean fillWithZeros)161     public int[] getIntArray(int size, boolean fillWithZeros) {
162         return new int[size];
163     }
164 
165     /**
166      * Puts the given int array to the cache. The caller must no longer
167      * use the array.
168      * <p>
169      * This implementation does nothing.
170      */
putArray(int[] array)171     public void putArray(int[] array) {}
172 }
173