Created
July 2, 2019 15:09
-
-
Save kaspernielsen/540aacaf0581e7be80b0ebe3348f4a24 to your computer and use it in GitHub Desktop.
LookupValue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Lazily associate a computed value with a lookup object much like {@link ClassValue} but for {@link Lookup} objects. | |
*/ | |
public abstract class LookupValue<T> { | |
/** The cache of values. */ | |
private final ClassValue<ConcurrentHashMap<Integer, T>> LOOKUP_CACHE = new ClassValue<>() { | |
/** {@inheritDoc} */ | |
@Override | |
protected ConcurrentHashMap<Integer, T> computeValue(Class<?> type) { | |
return new ConcurrentHashMap<Integer, T>(1); | |
} | |
}; | |
/** | |
* Computes the given lookup objects's derived value for this {@code LookupValue}. | |
* <p> | |
* This method will be invoked within the first thread that accesses the value with the {@link #get(Lookup) get} method. | |
* <p> | |
* If this method throws an exception, the corresponding call to {@code get} will terminate abnormally with that | |
* exception, and no lookup value will be recorded. | |
* | |
* @param lookup | |
* the lookup object for which a value must be computed | |
* @return the newly computed value associated with this {@code LookupValue}, for the given lookup object | |
*/ | |
protected abstract T computeValue(MethodHandles.Lookup lookup); | |
/** | |
* Returns the value for the given lookup object. If no value has yet been computed, it is obtained by an invocation of | |
* the {@link #computeValue computeValue} method. | |
* | |
* @param lookup | |
* the lookup object | |
* @return the value for the given lookup object | |
*/ | |
public final T get(MethodHandles.Lookup lookup) { | |
ConcurrentHashMap<Integer, T> chm = LOOKUP_CACHE.get(lookup.lookupClass()); | |
Integer lookupMode = Integer.valueOf(lookup.lookupModes()); | |
// we could just to chm.computeIfAbsent(..) but thats not garbage free | |
T value = chm.get(lookupMode); | |
if (value == null) { | |
value = chm.computeIfAbsent(lookupMode, ignore -> computeValue(lookup)); | |
} | |
return value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment