Browse Source

Util: Add cache which keeps a soft reference on the values

The values need to implement the SoftCache.Cacheable<K> interface
where K is the key type. By doing this they promise to keep a
reference to the key. Not doing so will eventually cause the value
from being removed from the cache.
pull/270/head
weisj 3 years ago
parent
commit
2577a5a168
No known key found for this signature in database
GPG Key ID: 31124CB75461DA2A
  1. 7
      utils/build.gradle.kts
  2. 67
      utils/src/main/java/com/github/weisj/darklaf/util/cache/SoftCache.java
  3. 1
      utils/src/main/module/module-info.java
  4. 78
      utils/src/test/java/com/github/weisj/darklaf/util/cache/SoftCacheTest.java

7
utils/build.gradle.kts

@ -5,4 +5,11 @@ plugins {
dependencies { dependencies {
compileOnly(libs.nullabilityAnnotations) compileOnly(libs.nullabilityAnnotations)
testImplementation(libs.test.junit.api)
testRuntimeOnly(libs.test.junit.engine)
}
tasks.test {
useJUnitPlatform()
} }

67
utils/src/main/java/com/github/weisj/darklaf/util/cache/SoftCache.java vendored

@ -0,0 +1,67 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.util.cache;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.WeakHashMap;
public class SoftCache<K, V extends SoftCache.Cacheable<K>> {
private final Map<K, SoftReference<V>> cache = new WeakHashMap<>();
public V get(final K key) {
Reference<V> reference = cache.get(key);
if (reference == null) return null;
V value = reference.get();
if (value == null) {
cache.remove(key);
}
return value;
}
public void put(final K key, final V value) {
if (value != null) {
cache.put(key, new SoftReference<>(value));
value.setCacheKey(key);
} else {
cache.remove(key);
}
}
public void clear() {
cache.clear();
}
public int size() {
return cache.size();
}
public boolean isEmpty() {
return cache.isEmpty();
}
public interface Cacheable<K> {
void setCacheKey(final K key);
}
}

1
utils/src/main/module/module-info.java

@ -29,6 +29,7 @@ module darklaf.utils {
requires static annotations; requires static annotations;
exports com.github.weisj.darklaf.util; exports com.github.weisj.darklaf.util;
exports com.github.weisj.darklaf.util.cache;
exports com.github.weisj.darklaf.util.graphics; exports com.github.weisj.darklaf.util.graphics;
exports com.github.weisj.darklaf.util.value; exports com.github.weisj.darklaf.util.value;
} }

78
utils/src/test/java/com/github/weisj/darklaf/util/cache/SoftCacheTest.java vendored

@ -0,0 +1,78 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.util.cache;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class SoftCacheTest {
@Test
void testValuesAreReleased() {
final int count = 500;
SoftCache<TestKey, TestValue> cache = new SoftCache<>();
Set<TestValue> hardReferences = new HashSet<>();
for (int i = 0; i < count; i++) {
TestValue value = new TestValue();
TestKey key = new TestKey();
hardReferences.add(value);
cache.put(key, value);
Assertions.assertEquals(key, value.key);
}
Assertions.assertEquals(count, hardReferences.size());
Assertions.assertEquals(count, cache.size());
hardReferences.clear();
waitForGarbageCollection(() -> !cache.isEmpty());
}
@SuppressWarnings({"unused"})
private void waitForGarbageCollection(final Supplier<Boolean> checker) {
while (checker.get()) {
Object object = null;
try {
object = new int[10][10][10][10][10][10][10][10][10][10][10][10];
} catch (OutOfMemoryError ignored) {
}
System.out.println(object);
System.gc();
}
}
private static class TestKey {
}
private static class TestValue implements SoftCache.Cacheable<TestKey> {
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private TestKey key;
@Override
public void setCacheKey(TestKey key) {
this.key = key;
}
}
}
Loading…
Cancel
Save