154 lines
5.3 KiB
Java
154 lines
5.3 KiB
Java
![]() |
/* GENERATED SOURCE. DO NOT MODIFY. */
|
||
|
// © 2016 and later: Unicode, Inc. and others.
|
||
|
// License & terms of use: http://www.unicode.org/copyright.html
|
||
|
/*
|
||
|
*******************************************************************************
|
||
|
* Copyright (C) 2016, International Business Machines Corporation and
|
||
|
* others. All Rights Reserved.
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
package android.icu.impl;
|
||
|
|
||
|
import java.lang.ref.Reference;
|
||
|
import java.lang.ref.SoftReference;
|
||
|
|
||
|
import android.icu.util.ICUException;
|
||
|
|
||
|
/**
|
||
|
* Value type for cache items:
|
||
|
* Holds a value either via a direct reference or via a {@link Reference},
|
||
|
* depending on the current "strength" when {@code getInstance()} was called.
|
||
|
*
|
||
|
* <p>The value is <i>conceptually<i> immutable.
|
||
|
* If it is held via a direct reference, then it is actually immutable.
|
||
|
*
|
||
|
* <p>A {@code Reference} may be cleared (garbage-collected),
|
||
|
* after which {@code get()} returns null.
|
||
|
* It can then be reset via {@code resetIfAbsent()}.
|
||
|
* The new value should be the same as, or equivalent to, the old value.
|
||
|
*
|
||
|
* <p>Null values are supported. They can be distinguished from cleared values
|
||
|
* via {@code isNull()}.
|
||
|
*
|
||
|
* @param <V> Cache instance value type
|
||
|
* @hide Only a subset of ICU is exposed in Android
|
||
|
*/
|
||
|
public abstract class CacheValue<V> {
|
||
|
/**
|
||
|
* "Strength" of holding a value in CacheValue instances.
|
||
|
* The default strength is {@code SOFT}.
|
||
|
* @hide Only a subset of ICU is exposed in Android
|
||
|
*/
|
||
|
public enum Strength {
|
||
|
/**
|
||
|
* Subsequent {@code getInstance()}-created objects
|
||
|
* will hold direct references to their values.
|
||
|
*/
|
||
|
STRONG,
|
||
|
/**
|
||
|
* Subsequent {@code getInstance()}-created objects
|
||
|
* will hold {@link SoftReference}s to their values.
|
||
|
*/
|
||
|
SOFT
|
||
|
};
|
||
|
private static volatile Strength strength = Strength.SOFT;
|
||
|
|
||
|
@SuppressWarnings("rawtypes")
|
||
|
private static final CacheValue NULL_VALUE = new NullValue();
|
||
|
|
||
|
/**
|
||
|
* Changes the "strength" of value references for subsequent {@code getInstance()} calls.
|
||
|
*/
|
||
|
public static void setStrength(Strength strength) { CacheValue.strength = strength; }
|
||
|
|
||
|
/**
|
||
|
* Returns true if the "strength" is set to {@code STRONG}.
|
||
|
*/
|
||
|
public static boolean futureInstancesWillBeStrong() { return strength == Strength.STRONG; }
|
||
|
|
||
|
/**
|
||
|
* Returns a CacheValue instance that holds the value.
|
||
|
* It holds it directly if the value is null or if the current "strength" is {@code STRONG}.
|
||
|
* Otherwise, it holds it via a {@link Reference}.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public static <V> CacheValue<V> getInstance(V value) {
|
||
|
if (value == null) {
|
||
|
return NULL_VALUE;
|
||
|
}
|
||
|
return strength == Strength.STRONG ? new StrongValue<V>(value) : new SoftValue<V>(value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Distinguishes a null value from a Reference value that has been cleared.
|
||
|
*
|
||
|
* @return true if this object represents a null value.
|
||
|
*/
|
||
|
public boolean isNull() { return false; }
|
||
|
/**
|
||
|
* Returns the value (which can be null),
|
||
|
* or null if it was held in a Reference and has been cleared.
|
||
|
*/
|
||
|
public abstract V get();
|
||
|
/**
|
||
|
* If the value was held via a {@link Reference} which has been cleared,
|
||
|
* then it is replaced with a new {@link Reference} to the new value,
|
||
|
* and the new value is returned.
|
||
|
* The old and new values should be the same or equivalent.
|
||
|
*
|
||
|
* <p>Otherwise the old value is returned.
|
||
|
*
|
||
|
* @param value Replacement value, for when the current {@link Reference} has been cleared.
|
||
|
* @return The old or new value.
|
||
|
*/
|
||
|
public abstract V resetIfCleared(V value);
|
||
|
|
||
|
private static final class NullValue<V> extends CacheValue<V> {
|
||
|
@Override
|
||
|
public boolean isNull() { return true; }
|
||
|
@Override
|
||
|
public V get() { return null; }
|
||
|
@Override
|
||
|
public V resetIfCleared(V value) {
|
||
|
if (value != null) {
|
||
|
throw new ICUException("resetting a null value to a non-null value");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static final class StrongValue<V> extends CacheValue<V> {
|
||
|
private V value;
|
||
|
|
||
|
StrongValue(V value) { this.value = value; }
|
||
|
@Override
|
||
|
public V get() { return value; }
|
||
|
@Override
|
||
|
public V resetIfCleared(V value) {
|
||
|
// value and this.value should be equivalent, but
|
||
|
// we do not require equals() to be implemented appropriately.
|
||
|
return this.value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static final class SoftValue<V> extends CacheValue<V> {
|
||
|
private volatile Reference<V> ref; // volatile for unsynchronized get()
|
||
|
|
||
|
SoftValue(V value) { ref = new SoftReference<V>(value); }
|
||
|
@Override
|
||
|
public V get() { return ref.get(); }
|
||
|
@Override
|
||
|
public synchronized V resetIfCleared(V value) {
|
||
|
V oldValue = ref.get();
|
||
|
if (oldValue == null) {
|
||
|
ref = new SoftReference<V>(value);
|
||
|
return value;
|
||
|
} else {
|
||
|
// value and oldValue should be equivalent, but
|
||
|
// we do not require equals() to be implemented appropriately.
|
||
|
return oldValue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|