Corrected false assumption in caching logic.
This commit is contained in:
parent
f637e79ea5
commit
f7eb94ae39
@ -57,15 +57,16 @@ public class Cache<K, V> {
|
|||||||
* @return the value associated to the key.
|
* @return the value associated to the key.
|
||||||
*/
|
*/
|
||||||
public V get(K key) {
|
public V get(K key) {
|
||||||
readLock.lock();
|
|
||||||
CacheValue<K, V> value = null;
|
CacheValue<K, V> value = null;
|
||||||
try {
|
|
||||||
if (!data.containsKey(key)) return null;
|
|
||||||
value = data.get(key);
|
value = data.get(key);
|
||||||
|
if (value == null) return null;
|
||||||
|
if (readLock.tryLock()) {
|
||||||
|
try {
|
||||||
usage.tryMoveToTop(value);
|
usage.tryMoveToTop(value);
|
||||||
} finally {
|
} finally {
|
||||||
readLock.unlock();
|
readLock.unlock();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return value.value;
|
return value.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,27 +7,28 @@ class CacheUsageStack<K, V> {
|
|||||||
private volatile CacheValue<K, V> first, last;
|
private volatile CacheValue<K, V> first, last;
|
||||||
private final ReentrantLock lock = new ReentrantLock();
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
private void addToTop(CacheValue<K, V> value) {
|
private void addValueToStackTop(CacheValue<K, V> value) {
|
||||||
if (first != null) {
|
if (first != null) {
|
||||||
first.front = value;
|
first.front = value;
|
||||||
value.back = first;
|
value.back = first;
|
||||||
} else {
|
} else {
|
||||||
last = value;
|
last = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
value.front = null;
|
value.front = null;
|
||||||
first = value;
|
first = value;
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeValue(CacheValue<K, V> value) {
|
private void removeValueFromStack(CacheValue<K, V> value) {
|
||||||
if (value.front != null) {
|
if (value.front != null) {
|
||||||
value.front.back = value.back;
|
value.front.back = value.back;
|
||||||
} else {
|
} else if (first == value) {
|
||||||
first = value.back;
|
first = value.back;
|
||||||
}
|
}
|
||||||
if (value.back != null) {
|
if (value.back != null) {
|
||||||
value.back.front = value.front;
|
value.back.front = value.front;
|
||||||
} else {
|
} else if (last == value) {
|
||||||
last = value.front;
|
last = value.front;
|
||||||
}
|
}
|
||||||
value.front = null;
|
value.front = null;
|
||||||
@ -38,8 +39,10 @@ class CacheUsageStack<K, V> {
|
|||||||
public void moveToTop(CacheValue<K, V> value) {
|
public void moveToTop(CacheValue<K, V> value) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
removeValue(value);
|
if (!value.detached) {
|
||||||
addToTop(value);
|
removeValueFromStack(value);
|
||||||
|
addValueToStackTop(value);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -50,8 +53,7 @@ class CacheUsageStack<K, V> {
|
|||||||
success = lock.tryLock();
|
success = lock.tryLock();
|
||||||
if (success) {
|
if (success) {
|
||||||
try {
|
try {
|
||||||
removeValue(value);
|
moveToTop(value);
|
||||||
addToTop(value);
|
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -62,7 +64,7 @@ class CacheUsageStack<K, V> {
|
|||||||
public void add(CacheValue<K, V> value) {
|
public void add(CacheValue<K, V> value) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
addToTop(value);
|
addValueToStackTop(value);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -73,7 +75,8 @@ class CacheUsageStack<K, V> {
|
|||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
cacheValue = last;
|
cacheValue = last;
|
||||||
removeValue(last);
|
removeValueFromStack(last);
|
||||||
|
cacheValue.detached = true;
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,23 @@
|
|||||||
package ca.recrown.islandsurvivalcraft.caching;
|
package ca.recrown.islandsurvivalcraft.caching;
|
||||||
|
|
||||||
class CacheValue<KeyType, ValueType> {
|
class CacheValue<KeyType, ValueType> {
|
||||||
|
/**
|
||||||
|
* The key that represents this cache value in the caches hashmap.
|
||||||
|
*/
|
||||||
public volatile KeyType key;
|
public volatile KeyType key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual value that this cache value stores.
|
||||||
|
*/
|
||||||
public volatile ValueType value;
|
public volatile ValueType value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache value in this position.
|
||||||
|
*/
|
||||||
public volatile CacheValue<KeyType, ValueType> front, back;
|
public volatile CacheValue<KeyType, ValueType> front, back;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not this value is detached from the cache's hashmap.
|
||||||
|
*/
|
||||||
|
public volatile boolean detached;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user