Home | History | Annotate | Download | only in impl
      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