Skip to content

Commit b96b000

Browse files
sjuddglide-copybara-robot
authored andcommittedJun 26, 2019
Avoid holding the Engine lock while calling callbacks for in memory resources.
Doing so can make it easy for callers to deadlock. PiperOrigin-RevId: 255250190
1 parent 8907122 commit b96b000

File tree

1 file changed

+84
-24
lines changed
  • library/src/main/java/com/bumptech/glide/load/engine

1 file changed

+84
-24
lines changed
 

‎library/src/main/java/com/bumptech/glide/load/engine/Engine.java

+84-24
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public Engine(
152152
* @param height The target height in pixels of the desired resource.
153153
* @param cb The callback that will be called when the load completes.
154154
*/
155-
public synchronized <R> LoadStatus load(
155+
public <R> LoadStatus load(
156156
GlideContext glideContext,
157157
Object model,
158158
Key signature,
@@ -185,24 +185,65 @@ public synchronized <R> LoadStatus load(
185185
transcodeClass,
186186
options);
187187

188-
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
189-
if (active != null) {
190-
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
191-
if (VERBOSE_IS_LOGGABLE) {
192-
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
193-
}
194-
return null;
195-
}
188+
EngineResource<?> memoryResource;
189+
synchronized (this) {
190+
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
196191

197-
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
198-
if (cached != null) {
199-
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
200-
if (VERBOSE_IS_LOGGABLE) {
201-
logWithTimeAndKey("Loaded resource from cache", startTime, key);
192+
if (memoryResource == null) {
193+
return waitForExistingOrStartNewJob(
194+
glideContext,
195+
model,
196+
signature,
197+
width,
198+
height,
199+
resourceClass,
200+
transcodeClass,
201+
priority,
202+
diskCacheStrategy,
203+
transformations,
204+
isTransformationRequired,
205+
isScaleOnlyOrNoTransform,
206+
options,
207+
isMemoryCacheable,
208+
useUnlimitedSourceExecutorPool,
209+
useAnimationPool,
210+
onlyRetrieveFromCache,
211+
cb,
212+
callbackExecutor,
213+
key,
214+
startTime);
202215
}
203-
return null;
204216
}
205217

218+
// Avoid calling back while holding the engine lock, doing so makes it easier for callers to
219+
// deadlock.
220+
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
221+
return null;
222+
}
223+
224+
private <R> LoadStatus waitForExistingOrStartNewJob(
225+
GlideContext glideContext,
226+
Object model,
227+
Key signature,
228+
int width,
229+
int height,
230+
Class<?> resourceClass,
231+
Class<R> transcodeClass,
232+
Priority priority,
233+
DiskCacheStrategy diskCacheStrategy,
234+
Map<Class<?>, Transformation<?>> transformations,
235+
boolean isTransformationRequired,
236+
boolean isScaleOnlyOrNoTransform,
237+
Options options,
238+
boolean isMemoryCacheable,
239+
boolean useUnlimitedSourceExecutorPool,
240+
boolean useAnimationPool,
241+
boolean onlyRetrieveFromCache,
242+
ResourceCallback cb,
243+
Executor callbackExecutor,
244+
EngineKey key,
245+
long startTime) {
246+
206247
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
207248
if (current != null) {
208249
current.addCallback(cb, callbackExecutor);
@@ -250,15 +291,38 @@ public synchronized <R> LoadStatus load(
250291
return new LoadStatus(cb, engineJob);
251292
}
252293

294+
@Nullable
295+
private EngineResource<?> loadFromMemory(
296+
EngineKey key, boolean isMemoryCacheable, long startTime) {
297+
if (!isMemoryCacheable) {
298+
return null;
299+
}
300+
301+
EngineResource<?> active = loadFromActiveResources(key);
302+
if (active != null) {
303+
if (VERBOSE_IS_LOGGABLE) {
304+
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
305+
}
306+
return active;
307+
}
308+
309+
EngineResource<?> cached = loadFromCache(key);
310+
if (cached != null) {
311+
if (VERBOSE_IS_LOGGABLE) {
312+
logWithTimeAndKey("Loaded resource from cache", startTime, key);
313+
}
314+
return cached;
315+
}
316+
317+
return null;
318+
}
319+
253320
private static void logWithTimeAndKey(String log, long startTime, Key key) {
254321
Log.v(TAG, log + " in " + LogTime.getElapsedMillis(startTime) + "ms, key: " + key);
255322
}
256323

257324
@Nullable
258-
private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
259-
if (!isMemoryCacheable) {
260-
return null;
261-
}
325+
private EngineResource<?> loadFromActiveResources(Key key) {
262326
EngineResource<?> active = activeResources.get(key);
263327
if (active != null) {
264328
active.acquire();
@@ -267,11 +331,7 @@ private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCache
267331
return active;
268332
}
269333

270-
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
271-
if (!isMemoryCacheable) {
272-
return null;
273-
}
274-
334+
private EngineResource<?> loadFromCache(Key key) {
275335
EngineResource<?> cached = getEngineResourceFromCache(key);
276336
if (cached != null) {
277337
cached.acquire();

0 commit comments

Comments
 (0)
Please sign in to comment.