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 java.lang;
27
28 import java.util.WeakHashMap;
29 import java.lang.ref.WeakReference;
30 import java.util.concurrent.atomic.AtomicInteger;
31
32 import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;
33 import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;
34
35 /**
36 * Lazily associate a computed value with (potentially) every type.
37 * For example, if a dynamic language needs to construct a message dispatch
38 * table for each class encountered at a message send call site,
39 * it can use a {@code ClassValue} to cache information needed to
40 * perform the message send quickly, for each class encountered.
41 * @author John Rose, JSR 292 EG
42 * @since 1.7
43 */
44 public abstract class ClassValue<T> {
45 /**
46 * Sole constructor. (For invocation by subclass constructors, typically
47 * implicit.)
48 */
49 protected ClassValue() {
50 }
51
394 // or if the version goes immediately dead and is nulled out,
395 // the reader will take the slow path and retry under a lock.
396 }
397
398 // The following class could also be top level and non-public:
399
400 /** A backing map for all ClassValues.
401 * Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).
402 * Also manages an unserialized fast-path cache.
403 */
404 static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {
405 private Entry<?>[] cacheArray;
406 private int cacheLoad, cacheLoadLimit;
407
408 /** Number of entries initially allocated to each type when first used with any ClassValue.
409 * It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.
410 * Must be a power of 2.
411 */
412 private static final int INITIAL_ENTRIES = 32;
413
414 /** Build a backing map for ClassValues.
415 * Also, create an empty cache array and install it on the class.
416 */
417 ClassValueMap() {
418 sizeCache(INITIAL_ENTRIES);
419 }
420
421 Entry<?>[] getCache() { return cacheArray; }
422
423 /** Initiate a query. Store a promise (placeholder) if there is no value yet. */
424 synchronized
425 <T> Entry<T> startEntry(ClassValue<T> classValue) {
426 @SuppressWarnings("unchecked") // one map has entries for all value types <T>
427 Entry<T> e = (Entry<T>) get(classValue.identity);
428 Version<T> v = classValue.version();
429 if (e == null) {
430 e = v.promise();
431 // The presence of a promise means that a value is pending for v.
432 // Eventually, finishEntry will overwrite the promise.
433 put(classValue.identity, e);
434 // Note that the promise is never entered into the cache!
435 return e;
436 } else if (e.isPromise()) {
437 // Somebody else has asked the same question.
438 // Let the races begin!
|
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 java.lang;
27
28 import java.util.WeakHashMap;
29 import java.lang.ref.WeakReference;
30 import java.util.concurrent.atomic.AtomicInteger;
31
32 import jdk.internal.misc.Unsafe;
33
34 import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;
35 import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;
36
37 /**
38 * Lazily associate a computed value with (potentially) every type.
39 * For example, if a dynamic language needs to construct a message dispatch
40 * table for each class encountered at a message send call site,
41 * it can use a {@code ClassValue} to cache information needed to
42 * perform the message send quickly, for each class encountered.
43 * @author John Rose, JSR 292 EG
44 * @since 1.7
45 */
46 public abstract class ClassValue<T> {
47 /**
48 * Sole constructor. (For invocation by subclass constructors, typically
49 * implicit.)
50 */
51 protected ClassValue() {
52 }
53
396 // or if the version goes immediately dead and is nulled out,
397 // the reader will take the slow path and retry under a lock.
398 }
399
400 // The following class could also be top level and non-public:
401
402 /** A backing map for all ClassValues.
403 * Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).
404 * Also manages an unserialized fast-path cache.
405 */
406 static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {
407 private Entry<?>[] cacheArray;
408 private int cacheLoad, cacheLoadLimit;
409
410 /** Number of entries initially allocated to each type when first used with any ClassValue.
411 * It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.
412 * Must be a power of 2.
413 */
414 private static final int INITIAL_ENTRIES = 32;
415
416 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
417
418 /** Build a backing map for ClassValues.
419 * Also, create an empty cache array and install it on the class.
420 */
421 ClassValueMap() {
422 sizeCache(INITIAL_ENTRIES);
423 // Trailing release fence to get safe publication
424 UNSAFE.storeFence();
425 }
426
427 Entry<?>[] getCache() { return cacheArray; }
428
429 /** Initiate a query. Store a promise (placeholder) if there is no value yet. */
430 synchronized
431 <T> Entry<T> startEntry(ClassValue<T> classValue) {
432 @SuppressWarnings("unchecked") // one map has entries for all value types <T>
433 Entry<T> e = (Entry<T>) get(classValue.identity);
434 Version<T> v = classValue.version();
435 if (e == null) {
436 e = v.promise();
437 // The presence of a promise means that a value is pending for v.
438 // Eventually, finishEntry will overwrite the promise.
439 put(classValue.identity, e);
440 // Note that the promise is never entered into the cache!
441 return e;
442 } else if (e.isPromise()) {
443 // Somebody else has asked the same question.
444 // Let the races begin!
|