Corrected false assumption in caching logic.

This commit is contained in:
Harrison Deng 2020-04-30 00:09:58 -05:00
parent f637e79ea5
commit f7eb94ae39
3 changed files with 37 additions and 17 deletions

View File

@ -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;
} }

View File

@ -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();
} }

View File

@ -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;
} }