CachedValuesManager: clean up and break down into smaller methods

for the sake of JIT and DRY
This commit is contained in:
peter
2018-10-10 11:22:44 +02:00
parent bef90cec67
commit 7af0b5b5c4
2 changed files with 51 additions and 39 deletions
@@ -69,7 +69,7 @@ public abstract class CachedValuesManager {
return createCachedValue(provider, true);
}
public <T, D extends UserDataHolder, P> T getParameterizedCachedValue(@NotNull D dataHolder,
public <T, P> T getParameterizedCachedValue(@NotNull UserDataHolder dataHolder,
@NotNull Key<ParameterizedCachedValue<T,P>> key,
@NotNull ParameterizedCachedValueProvider<T, P> provider,
boolean trackValue,
@@ -85,6 +85,7 @@ public abstract class CachedValuesManager {
}
}
else {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (dataHolder) {
value = dataHolder.getUserData(key);
if (value == null) {
@@ -105,16 +106,16 @@ public abstract class CachedValuesManager {
* @param trackValue if value tracking required. T should be trackable in this case.
* @return up-to-date value.
*/
public abstract <T, D extends UserDataHolder> T getCachedValue(@NotNull D dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider,
boolean trackValue);
public abstract <T> T getCachedValue(@NotNull UserDataHolder dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider,
boolean trackValue);
/**
* Create a cached value with the given provider and non-tracked return value, store it in the first argument's user data. If it's already stored, reuse it.
* @return The cached value
*/
public <T, D extends UserDataHolder> T getCachedValue(@NotNull D dataHolder, @NotNull CachedValueProvider<T> provider) {
public <T> T getCachedValue(@NotNull UserDataHolder dataHolder, @NotNull CachedValueProvider<T> provider) {
return getCachedValue(dataHolder, this.getKeyForClass(provider.getClass()), provider, false);
}
@@ -50,44 +50,58 @@ public class CachedValuesManagerImpl extends CachedValuesManager {
@Override
@Nullable
public <T, D extends UserDataHolder> T getCachedValue(@NotNull D dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider,
boolean trackValue) {
public <T> T getCachedValue(@NotNull UserDataHolder dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider,
boolean trackValue) {
return dataHolder instanceof UserDataHolderEx
? getCachedValueFromExHolder((UserDataHolderEx)dataHolder, key, provider, trackValue)
: getCachedValueFromHolder(dataHolder, key, provider, trackValue);
}
private <T> T getCachedValueFromExHolder(@NotNull UserDataHolderEx dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider,
boolean trackValue) {
CachedValue<T> value = dataHolder.getUserData(key);
while (isOutdated(value)) {
if (dataHolder.replace(key, value, null)) {
value = null;
break;
}
value = dataHolder.getUserData(key);
}
if (value == null) {
value = dataHolder.putUserDataIfAbsent(key, freshCachedValue(dataHolder, key, provider, trackValue));
}
return value.getValue();
}
private <T> T getCachedValueFromHolder(@NotNull UserDataHolder dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider, boolean trackValue) {
CachedValue<T> value;
if (dataHolder instanceof UserDataHolderEx) {
UserDataHolderEx dh = (UserDataHolderEx)dataHolder;
value = dh.getUserData(key);
while (isOutdated(value)) {
if (dh.replace(key, value, null)) {
value = null;
break;
}
value = dh.getUserData(key);
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (dataHolder) {
value = dataHolder.getUserData(key);
if (isOutdated(value)) {
value = null;
}
if (value == null) {
CachedValueLeakChecker.checkProvider(provider, key, dataHolder);
value = createCachedValue(provider, trackValue);
assert ((CachedValueBase)value).isFromMyProject(myProject);
value = dh.putUserDataIfAbsent(key, value);
}
}
else {
synchronized (dataHolder) {
value = dataHolder.getUserData(key);
if (isOutdated(value)) {
value = null;
}
if (value == null) {
CachedValueLeakChecker.checkProvider(provider, key, dataHolder);
value = createCachedValue(provider, trackValue);
dataHolder.putUserData(key, value);
}
value = freshCachedValue(dataHolder, key, provider, trackValue);
dataHolder.putUserData(key, value);
}
}
return value.getValue();
}
private <T> CachedValue<T> freshCachedValue(UserDataHolder dh, Key<CachedValue<T>> key, CachedValueProvider<T> provider, boolean trackValue) {
CachedValueLeakChecker.checkProvider(provider, key, dh);
CachedValue<T> value = createCachedValue(provider, trackValue);
assert ((CachedValueBase)value).isFromMyProject(myProject);
return value;
}
private boolean isOutdated(CachedValue<?> value) {
return value instanceof CachedValueBase &&
(!((CachedValueBase)value).isFromMyProject(myProject) || hasOutdatedValue((CachedValueBase)value));
@@ -97,7 +111,4 @@ public class CachedValuesManagerImpl extends CachedValuesManager {
return !base.hasUpToDateValue() && base.getRawData() != null;
}
public Project getProject() {
return myProject;
}
}