From 01f5a3d3dc0e78cc83b9e390b331a65dd5c1a9f3 Mon Sep 17 00:00:00 2001
From: Sam Judd
Date: Thu, 7 Sep 2017 19:11:32 -0700
Subject: [PATCH] Key off of the safe key in writeLock in DiskLruCacheWrapper.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Key we’re given may have a different implementation for equals and hashCode than it does for updateDiskCacheKey. As a result, two different
Key objects that are not equal to each other may produce the same
disk cache key. To avoid simultaneous puts for the same disk cache key
we need to lock on the disk cache key, not the original key object.
---
.../engine/cache/DiskCacheWriteLocker.java | 19 +++++++++----------
.../engine/cache/DiskLruCacheWrapper.java | 6 +++---
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskCacheWriteLocker.java b/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskCacheWriteLocker.java
index 13318a8fc7..d11f0f02ac 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskCacheWriteLocker.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskCacheWriteLocker.java
@@ -1,6 +1,5 @@
package com.bumptech.glide.load.engine.cache;
-import com.bumptech.glide.load.Key;
import com.bumptech.glide.util.Preconditions;
import com.bumptech.glide.util.Synthetic;
import java.util.ArrayDeque;
@@ -19,16 +18,16 @@
* 0, the lock can safely be removed from the map.
*/
final class DiskCacheWriteLocker {
- private final Map locks = new HashMap<>();
+ private final Map locks = new HashMap<>();
private final WriteLockPool writeLockPool = new WriteLockPool();
- void acquire(Key key) {
+ void acquire(String safeKey) {
WriteLock writeLock;
synchronized (this) {
- writeLock = locks.get(key);
+ writeLock = locks.get(safeKey);
if (writeLock == null) {
writeLock = writeLockPool.obtain();
- locks.put(key, writeLock);
+ locks.put(safeKey, writeLock);
}
writeLock.interestedThreads++;
}
@@ -36,24 +35,24 @@ void acquire(Key key) {
writeLock.lock.lock();
}
- void release(Key key) {
+ void release(String safeKey) {
WriteLock writeLock;
synchronized (this) {
- writeLock = Preconditions.checkNotNull(locks.get(key));
+ writeLock = Preconditions.checkNotNull(locks.get(safeKey));
if (writeLock.interestedThreads < 1) {
throw new IllegalStateException("Cannot release a lock that is not held"
- + ", key: " + key
+ + ", safeKey: " + safeKey
+ ", interestedThreads: " + writeLock.interestedThreads);
}
writeLock.interestedThreads--;
if (writeLock.interestedThreads == 0) {
- WriteLock removed = locks.remove(key);
+ WriteLock removed = locks.remove(safeKey);
if (!removed.equals(writeLock)) {
throw new IllegalStateException("Removed the wrong lock"
+ ", expected to remove: " + writeLock
+ ", but actually removed: " + removed
- + ", key: " + key);
+ + ", safeKey: " + safeKey);
}
writeLockPool.offer(removed);
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskLruCacheWrapper.java b/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskLruCacheWrapper.java
index c0e6f52692..8cd104d02a 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskLruCacheWrapper.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/cache/DiskLruCacheWrapper.java
@@ -88,9 +88,9 @@ public File get(Key key) {
public void put(Key key, Writer writer) {
// We want to make sure that puts block so that data is available when put completes. We may
// actually not write any data if we find that data is written by the time we acquire the lock.
- writeLocker.acquire(key);
+ String safeKey = safeKeyGenerator.getSafeKey(key);
+ writeLocker.acquire(safeKey);
try {
- String safeKey = safeKeyGenerator.getSafeKey(key);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Put: Obtained: " + safeKey + " for for Key: " + key);
}
@@ -121,7 +121,7 @@ public void put(Key key, Writer writer) {
}
}
} finally {
- writeLocker.release(key);
+ writeLocker.release(safeKey);
}
}