Skip to content

Commit

Permalink
Fix a race causing an NPE when obtaining load paths for resources.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=178651500
  • Loading branch information
sjudd committed Dec 11, 2017
1 parent 2f76842 commit d427cbd
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 12 deletions.
6 changes: 5 additions & 1 deletion library/src/main/java/com/bumptech/glide/Registry.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bumptech.glide;

import android.support.annotation.Nullable;
import android.support.v4.util.Pools.Pool;
import com.bumptech.glide.load.Encoder;
import com.bumptech.glide.load.ImageHeaderParser;
Expand Down Expand Up @@ -446,11 +447,14 @@ public <Model, Data> Registry replace(
return this;
}

@Nullable
public <Data, TResource, Transcode> LoadPath<Data, TResource, Transcode> getLoadPath(
Class<Data> dataClass, Class<TResource> resourceClass, Class<Transcode> transcodeClass) {
LoadPath<Data, TResource, Transcode> result =
loadPathCache.get(dataClass, resourceClass, transcodeClass);
if (result == null && !loadPathCache.contains(dataClass, resourceClass, transcodeClass)) {
if (loadPathCache.isEmptyLoadPath(result)) {
return null;
} else if (result == null) {
List<DecodePath<Data, TResource, Transcode>> decodePaths =
getDecodePaths(dataClass, resourceClass, transcodeClass);
// It's possible there is no way to decode or transcode to the desired types from a given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,50 @@

import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import com.bumptech.glide.load.engine.DecodePath;
import com.bumptech.glide.load.engine.LoadPath;
import com.bumptech.glide.load.resource.transcode.UnitTranscoder;
import com.bumptech.glide.util.MultiClassKey;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;

/**
* Maintains a cache of data, resource, and transcode classes to available
* {@link com.bumptech.glide.load.engine.LoadPath}s capable of decoding with the requested types.
*/
public class LoadPathCache {
private static final LoadPath<?, ?, ?> NO_PATHS_SIGNAL =
new LoadPath<>(
Object.class,
Object.class,
Object.class,
Collections.singletonList(
new DecodePath<>(
Object.class,
Object.class,
Object.class,
Collections.emptyList(),
new UnitTranscoder<>(),
/*listPool=*/ null)),
/*listPool=*/ null);

private final ArrayMap<MultiClassKey, LoadPath<?, ?, ?>> cache = new ArrayMap<>();
private final AtomicReference<MultiClassKey> keyRef = new AtomicReference<>();

public boolean contains(Class<?> dataClass, Class<?> resourceClass, Class<?> transcodeClass) {
MultiClassKey key = getKey(dataClass, resourceClass, transcodeClass);
boolean result;
synchronized (cache) {
result = cache.containsKey(key);
}
keyRef.set(key);
return result;
/**
* Returns {@code} true if the given {@link LoadPath} is the signal object returned from
* {@link #get(Class, Class, Class)} that indicates that we've previously found that there are
* no available paths to load the requested resources and {@code false} otherwise.
*/
public boolean isEmptyLoadPath(@Nullable LoadPath<?, ?, ?> path) {
return NO_PATHS_SIGNAL.equals(path);
}

/**
* May return {@link #NO_PATHS_SIGNAL} to indicate that we've previously found that there are 0
* available load paths for the requested types. Callers must check using
* {@link #isEmptyLoadPath(LoadPath)} before using any load path returned by this method.
*/
@SuppressWarnings("unchecked")
@Nullable
public <Data, TResource, Transcode> LoadPath<Data, TResource, Transcode> get(
Expand All @@ -38,10 +60,14 @@ public <Data, TResource, Transcode> LoadPath<Data, TResource, Transcode> get(
return (LoadPath<Data, TResource, Transcode>) result;
}

public void put(Class<?> dataClass, Class<?> resourceClass, Class<?> transcodeClass,
LoadPath<?, ?, ?> loadPath) {
public void put(
Class<?> dataClass, Class<?> resourceClass,
Class<?> transcodeClass,
@Nullable LoadPath<?, ?, ?> loadPath) {
synchronized (cache) {
cache.put(new MultiClassKey(dataClass, resourceClass, transcodeClass), loadPath);
cache.put(
new MultiClassKey(dataClass, resourceClass, transcodeClass),
loadPath != null ? loadPath : NO_PATHS_SIGNAL);
}
}

Expand Down

0 comments on commit d427cbd

Please sign in to comment.