Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/misc/Cache.java
38829 views
1
/*
2
* Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.misc;
27
28
import java.util.Dictionary;
29
import java.util.Enumeration;
30
import java.util.NoSuchElementException;
31
32
/**
33
* Caches the collision list.
34
*/
35
class CacheEntry extends Ref {
36
int hash;
37
Object key;
38
CacheEntry next;
39
public Object reconstitute() {
40
return null;
41
}
42
}
43
44
/**
45
* The Cache class. Maps keys to values. Any object can be used as
46
* a key and/or value. This is very similar to the Hashtable
47
* class, except that after putting an object into the Cache,
48
* it is not guaranteed that a subsequent get will return it.
49
* The Cache will automatically remove entries if memory is
50
* getting tight and if the entry is not referenced from outside
51
* the Cache.<p>
52
*
53
* To sucessfully store and retrieve objects from a hash table the
54
* object used as the key must implement the hashCode() and equals()
55
* methods.<p>
56
*
57
* This example creates a Cache of numbers. It uses the names of
58
* the numbers as keys:
59
* <pre>
60
* Cache numbers = new Cache();
61
* numbers.put("one", new Integer(1));
62
* numbers.put("two", new Integer(1));
63
* numbers.put("three", new Integer(1));
64
* </pre>
65
* To retrieve a number use:
66
* <pre>
67
* Integer n = (Integer)numbers.get("two");
68
* if (n != null) {
69
* System.out.println("two = " + n);
70
* }
71
* </pre>
72
*
73
* @see java.lang.Object#hashCode
74
* @see java.lang.Object#equals
75
* @see sun.misc.Ref
76
*/
77
public
78
class Cache extends Dictionary {
79
/**
80
* The hash table data.
81
*/
82
private CacheEntry table[];
83
84
/**
85
* The total number of entries in the hash table.
86
*/
87
private int count;
88
89
/**
90
* Rehashes the table when count exceeds this threshold.
91
*/
92
private int threshold;
93
94
/**
95
* The load factor for the hashtable.
96
*/
97
private float loadFactor;
98
99
private void init(int initialCapacity, float loadFactor) {
100
if ((initialCapacity <= 0) || (loadFactor <= 0.0)) {
101
throw new IllegalArgumentException();
102
}
103
this.loadFactor = loadFactor;
104
table = new CacheEntry[initialCapacity];
105
threshold = (int) (initialCapacity * loadFactor);
106
}
107
108
/**
109
* Constructs a new, empty Cache with the specified initial
110
* capacity and the specified load factor.
111
* @param initialCapacity the initial number of buckets
112
* @param loadFactor a number between 0.0 and 1.0, it defines
113
* the threshold for rehashing the Cache into
114
* a bigger one.
115
* @exception IllegalArgumentException If the initial capacity
116
* is less than or equal to zero.
117
* @exception IllegalArgumentException If the load factor is
118
* less than or equal to zero.
119
*/
120
public Cache (int initialCapacity, float loadFactor) {
121
init(initialCapacity, loadFactor);
122
}
123
124
/**
125
* Constructs a new, empty Cache with the specified initial
126
* capacity.
127
* @param initialCapacity the initial number of buckets
128
*/
129
public Cache (int initialCapacity) {
130
init(initialCapacity, 0.75f);
131
}
132
133
/**
134
* Constructs a new, empty Cache. A default capacity and load factor
135
* is used. Note that the Cache will automatically grow when it gets
136
* full.
137
*/
138
public Cache () {
139
try {
140
init(101, 0.75f);
141
} catch (IllegalArgumentException ex) {
142
// This should never happen
143
throw new Error("panic");
144
}
145
}
146
147
/**
148
* Returns the number of elements contained within the Cache.
149
*/
150
public int size() {
151
return count;
152
}
153
154
/**
155
* Returns true if the Cache contains no elements.
156
*/
157
public boolean isEmpty() {
158
return count == 0;
159
}
160
161
/**
162
* Returns an enumeration of the Cache's keys.
163
* @see Cache#elements
164
* @see Enumeration
165
*/
166
public synchronized Enumeration keys() {
167
return new CacheEnumerator(table, true);
168
}
169
170
/**
171
* Returns an enumeration of the elements. Use the Enumeration methods
172
* on the returned object to fetch the elements sequentially.
173
* @see Cache#keys
174
* @see Enumeration
175
*/
176
public synchronized Enumeration elements() {
177
return new CacheEnumerator(table, false);
178
}
179
180
/**
181
* Gets the object associated with the specified key in the Cache.
182
* @param key the key in the hash table
183
* @returns the element for the key or null if the key
184
* is not defined in the hash table.
185
* @see Cache#put
186
*/
187
public synchronized Object get(Object key) {
188
CacheEntry tab[] = table;
189
int hash = key.hashCode();
190
int index = (hash & 0x7FFFFFFF) % tab.length;
191
for (CacheEntry e = tab[index]; e != null; e = e.next) {
192
if ((e.hash == hash) && e.key.equals(key)) {
193
return e.check();
194
}
195
}
196
return null;
197
}
198
199
/**
200
* Rehashes the contents of the table into a bigger table.
201
* This is method is called automatically when the Cache's
202
* size exceeds the threshold.
203
*/
204
protected void rehash() {
205
int oldCapacity = table.length;
206
CacheEntry oldTable[] = table;
207
208
int newCapacity = oldCapacity * 2 + 1;
209
CacheEntry newTable[] = new CacheEntry[newCapacity];
210
211
threshold = (int) (newCapacity * loadFactor);
212
table = newTable;
213
214
// System.out.println("rehash old=" + oldCapacity + ", new=" +
215
// newCapacity + ", thresh=" + threshold + ", count=" + count);
216
217
for (int i = oldCapacity; i-- > 0;) {
218
for (CacheEntry old = oldTable[i]; old != null;) {
219
CacheEntry e = old;
220
old = old.next;
221
if (e.check() != null) {
222
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
223
e.next = newTable[index];
224
newTable[index] = e;
225
} else
226
count--; /* remove entries that have disappeared */
227
}
228
}
229
}
230
231
/**
232
* Puts the specified element into the Cache, using the specified
233
* key. The element may be retrieved by doing a get() with the same
234
* key. The key and the element cannot be null.
235
* @param key the specified hashtable key
236
* @param value the specified element
237
* @return the old value of the key, or null if it did not have one.
238
* @exception NullPointerException If the value of the specified
239
* element is null.
240
* @see Cache#get
241
*/
242
public synchronized Object put(Object key, Object value) {
243
// Make sure the value is not null
244
if (value == null) {
245
throw new NullPointerException();
246
}
247
// Makes sure the key is not already in the cache.
248
CacheEntry tab[] = table;
249
int hash = key.hashCode();
250
int index = (hash & 0x7FFFFFFF) % tab.length;
251
CacheEntry ne = null;
252
for (CacheEntry e = tab[index]; e != null; e = e.next) {
253
if ((e.hash == hash) && e.key.equals(key)) {
254
Object old = e.check();
255
e.setThing(value);
256
return old;
257
} else if (e.check() == null)
258
ne = e; /* reuse old flushed value */
259
}
260
261
if (count >= threshold) {
262
// Rehash the table if the threshold is exceeded
263
rehash();
264
return put(key, value);
265
}
266
// Creates the new entry.
267
if (ne == null) {
268
ne = new CacheEntry ();
269
ne.next = tab[index];
270
tab[index] = ne;
271
count++;
272
}
273
ne.hash = hash;
274
ne.key = key;
275
ne.setThing(value);
276
return null;
277
}
278
279
/**
280
* Removes the element corresponding to the key. Does nothing if the
281
* key is not present.
282
* @param key the key that needs to be removed
283
* @return the value of key, or null if the key was not found.
284
*/
285
public synchronized Object remove(Object key) {
286
CacheEntry tab[] = table;
287
int hash = key.hashCode();
288
int index = (hash & 0x7FFFFFFF) % tab.length;
289
for (CacheEntry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
290
if ((e.hash == hash) && e.key.equals(key)) {
291
if (prev != null) {
292
prev.next = e.next;
293
} else {
294
tab[index] = e.next;
295
}
296
count--;
297
return e.check();
298
}
299
}
300
return null;
301
}
302
}
303
304
/**
305
* A Cache enumerator class. This class should remain opaque
306
* to the client. It will use the Enumeration interface.
307
*/
308
class CacheEnumerator implements Enumeration {
309
boolean keys;
310
int index;
311
CacheEntry table[];
312
CacheEntry entry;
313
314
CacheEnumerator (CacheEntry table[], boolean keys) {
315
this.table = table;
316
this.keys = keys;
317
this.index = table.length;
318
}
319
320
public boolean hasMoreElements() {
321
while (index >= 0) {
322
while (entry != null)
323
if (entry.check() != null)
324
return true;
325
else
326
entry = entry.next;
327
while (--index >= 0 && (entry = table[index]) == null) ;
328
}
329
return false;
330
}
331
332
public Object nextElement() {
333
while (index >= 0) {
334
if (entry == null)
335
while (--index >= 0 && (entry = table[index]) == null) ;
336
if (entry != null) {
337
CacheEntry e = entry;
338
entry = e.next;
339
if (e.check() != null)
340
return keys ? e.key : e.check();
341
}
342
}
343
throw new NoSuchElementException("CacheEnumerator");
344
}
345
346
}
347
348