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 */ 41 public enum Strength { 42 /** 43 * Subsequent {@code getInstance()}-created objects 44 * will hold direct references to their values. 45 */ 46 STRONG, 47 /** 48 * Subsequent {@code getInstance()}-created objects 49 * will hold {@link SoftReference}s to their values. 50 */ 51 SOFT 52 }; 53 private static volatile Strength strength = Strength.SOFT; 54 55 @SuppressWarnings("rawtypes") 56 private static final CacheValue NULL_VALUE = new NullValue(); 57 58 /** 59 * Changes the "strength" of value references for subsequent {@code getInstance()} calls. 60 */ 61 public static void setStrength(Strength strength) { CacheValue.strength = strength; } 62 63 /** 64 * Returns true if the "strength" is set to {@code STRONG}. 65 */ 66 public static boolean futureInstancesWillBeStrong() { return strength == Strength.STRONG; } 67 68 /** 69 * Returns a CacheValue instance that holds the value. 70 * It holds it directly if the value is null or if the current "strength" is {@code STRONG}. 71 * Otherwise, it holds it via a {@link Reference}. 72 */ 73 @SuppressWarnings("unchecked") 74 public static <V> CacheValue<V> getInstance(V value) { 75 if (value == null) { 76 return NULL_VALUE; 77 } 78 return strength == Strength.STRONG ? new StrongValue<V>(value) : new SoftValue<V>(value); 79 } 80 81 /** 82 * Distinguishes a null value from a Reference value that has been cleared. 83 * 84 * @return true if this object represents a null value. 85 */ 86 public boolean isNull() { return false; } 87 /** 88 * Returns the value (which can be null), 89 * or null if it was held in a Reference and has been cleared. 90 */ 91 public abstract V get(); 92 /** 93 * If the value was held via a {@link Reference} which has been cleared, 94 * then it is replaced with a new {@link Reference} to the new value, 95 * and the new value is returned. 96 * The old and new values should be the same or equivalent. 97 * 98 * <p>Otherwise the old value is returned. 99 * 100 * @param value Replacement value, for when the current {@link Reference} has been cleared. 101 * @return The old or new value. 102 */ 103 public abstract V resetIfCleared(V value); 104 105 private static final class NullValue<V> extends CacheValue<V> { 106 @Override 107 public boolean isNull() { return true; } 108 @Override 109 public V get() { return null; } 110 @Override 111 public V resetIfCleared(V value) { 112 if (value != null) { 113 throw new ICUException("resetting a null value to a non-null value"); 114 } 115 return null; 116 } 117 } 118 119 private static final class StrongValue<V> extends CacheValue<V> { 120 private V value; 121 122 StrongValue(V value) { this.value = value; } 123 @Override 124 public V get() { return value; } 125 @Override 126 public V resetIfCleared(V value) { 127 // value and this.value should be equivalent, but 128 // we do not require equals() to be implemented appropriately. 129 return this.value; 130 } 131 } 132 133 private static final class SoftValue<V> extends CacheValue<V> { 134 private volatile Reference<V> ref; // volatile for unsynchronized get() 135 136 SoftValue(V value) { ref = new SoftReference<V>(value); } 137 @Override 138 public V get() { return ref.get(); } 139 @Override 140 public synchronized V resetIfCleared(V value) { 141 V oldValue = ref.get(); 142 if (oldValue == null) { 143 ref = new SoftReference<V>(value); 144 return value; 145 } else { 146 // value and oldValue should be equivalent, but 147 // we do not require equals() to be implemented appropriately. 148 return oldValue; 149 } 150 } 151 } 152 } 153