1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package android.icu.impl; 11 12 import java.lang.ref.Reference; 13 import java.lang.ref.SoftReference; 14 15 import android.icu.util.ICUException; 16 17 /** 18 * Value type for cache items: 19 * Holds a value either via a direct reference or via a {@link Reference}, 20 * depending on the current "strength" when {@code getInstance()} was called. 21 * 22 * <p>The value is <i>conceptually<i> immutable. 23 * If it is held via a direct reference, then it is actually immutable. 24 * 25 * <p>A {@code Reference} may be cleared (garbage-collected), 26 * after which {@code get()} returns null. 27 * It can then be reset via {@code resetIfAbsent()}. 28 * The new value should be the same as, or equivalent to, the old value. 29 * 30 * <p>Null values are supported. They can be distinguished from cleared values 31 * via {@code isNull()}. 32 * 33 * @param <V> Cache instance value type 34 * @hide Only a subset of ICU is exposed in Android 35 */ 36 public abstract class CacheValue<V> { 37 /** 38 * "Strength" of holding a value in CacheValue instances. 39 * The default strength is {@code SOFT}. 40 * @hide Only a subset of ICU is exposed in Android 41 */ 42 public enum Strength { 43 /** 44 * Subsequent {@code getInstance()}-created objects 45 * will hold direct references to their values. 46 */ 47 STRONG, 48 /** 49 * Subsequent {@code getInstance()}-created objects 50 * will hold {@link SoftReference}s to their values. 51 */ 52 SOFT 53 }; 54 private static volatile Strength strength = Strength.SOFT; 55 56 @SuppressWarnings("rawtypes") 57 private static final CacheValue NULL_VALUE = new NullValue(); 58 59 /** 60 * Changes the "strength" of value references for subsequent {@code getInstance()} calls. 61 */ 62 public static void setStrength(Strength strength) { CacheValue.strength = strength; } 63 64 /** 65 * Returns true if the "strength" is set to {@code STRONG}. 66 */ 67 public static boolean futureInstancesWillBeStrong() { return strength == Strength.STRONG; } 68 69 /** 70 * Returns a CacheValue instance that holds the value. 71 * It holds it directly if the value is null or if the current "strength" is {@code STRONG}. 72 * Otherwise, it holds it via a {@link Reference}. 73 */ 74 @SuppressWarnings("unchecked") 75 public static <V> CacheValue<V> getInstance(V value) { 76 if (value == null) { 77 return NULL_VALUE; 78 } 79 return strength == Strength.STRONG ? new StrongValue<V>(value) : new SoftValue<V>(value); 80 } 81 82 /** 83 * Distinguishes a null value from a Reference value that has been cleared. 84 * 85 * @return true if this object represents a null value. 86 */ 87 public boolean isNull() { return false; } 88 /** 89 * Returns the value (which can be null), 90 * or null if it was held in a Reference and has been cleared. 91 */ 92 public abstract V get(); 93 /** 94 * If the value was held via a {@link Reference} which has been cleared, 95 * then it is replaced with a new {@link Reference} to the new value, 96 * and the new value is returned. 97 * The old and new values should be the same or equivalent. 98 * 99 * <p>Otherwise the old value is returned. 100 * 101 * @param value Replacement value, for when the current {@link Reference} has been cleared. 102 * @return The old or new value. 103 */ 104 public abstract V resetIfCleared(V value); 105 106 private static final class NullValue<V> extends CacheValue<V> { 107 @Override 108 public boolean isNull() { return true; } 109 @Override 110 public V get() { return null; } 111 @Override 112 public V resetIfCleared(V value) { 113 if (value != null) { 114 throw new ICUException("resetting a null value to a non-null value"); 115 } 116 return null; 117 } 118 } 119 120 private static final class StrongValue<V> extends CacheValue<V> { 121 private V value; 122 123 StrongValue(V value) { this.value = value; } 124 @Override 125 public V get() { return value; } 126 @Override 127 public V resetIfCleared(V value) { 128 // value and this.value should be equivalent, but 129 // we do not require equals() to be implemented appropriately. 130 return this.value; 131 } 132 } 133 134 private static final class SoftValue<V> extends CacheValue<V> { 135 private volatile Reference<V> ref; // volatile for unsynchronized get() 136 137 SoftValue(V value) { ref = new SoftReference<V>(value); } 138 @Override 139 public V get() { return ref.get(); } 140 @Override 141 public synchronized V resetIfCleared(V value) { 142 V oldValue = ref.get(); 143 if (oldValue == null) { 144 ref = new SoftReference<V>(value); 145 return value; 146 } else { 147 // value and oldValue should be equivalent, but 148 // we do not require equals() to be implemented appropriately. 149 return oldValue; 150 } 151 } 152 } 153 } 154