X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=inline;f=bundles%2Forg.simantics.utils.datastructures%2Fsrc%2Forg%2Fsimantics%2Futils%2Fdatastructures%2Fcache%2FSoftTimedCache.java;h=6e9ed074c6317931ab7609e91a088f62b5565e4b;hb=c0941146a40af9df766b514fd4238aa20ec2ff4f;hp=40f47526417eb6fe592d975e3a65f271b472a1c3;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/cache/SoftTimedCache.java b/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/cache/SoftTimedCache.java
index 40f475264..6e9ed074c 100644
--- a/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/cache/SoftTimedCache.java
+++ b/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/cache/SoftTimedCache.java
@@ -1,223 +1,223 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
- * in Industry THTH ry.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics.utils.datastructures.cache;
-
-import java.lang.ref.SoftReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Timer;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.simantics.utils.threads.ThreadUtils;
-
-/**
- * A timed (Key, Value) cache which disposes the cached entry after the
- * specified amount of time if it is not removed from the cache. The hold time
- * is given to the {@link #put(Object, Object, long)} method, separately for
- * each value.
- *
- *
- * The cached values are held as soft references, which makes them collectible
- * under memory pressure, even before their hold time has ran out.
- *
- * @author Tuukka Lehtonen
- *
- * @param key type, held by strong references
- * @param value type, held by soft references to allow collection of the
- * cached elements when under memory pressure
- */
-public class SoftTimedCache implements ITimedCache {
-
- protected class Entry {
- final K key;
- final SoftReference ref;
- long holdTime;
- TimeUnit unit;
-
- ScheduledFuture> future;
-
- Entry(K k, V v, long holdTime, TimeUnit unit) {
- assert k != null;
- assert v != null;
-
- this.key = k;
- this.ref = new SoftReference(v);
- this.holdTime = holdTime;
- this.unit = unit;
- }
- }
-
- private final Map cache = Collections.synchronizedMap(new HashMap());
-
- @SuppressWarnings("unused")
- private String name;
-
- private Timer timer;
-
- public SoftTimedCache() {
- this("Cache Timer");
- }
-
- public SoftTimedCache(String name) {
- this.name = name;
- }
-
- public int size() {
- return cache.size();
- }
-
- @Override
- protected void finalize() throws Throwable {
- if (timer != null) {
- timer.cancel();
- }
- clear();
- super.finalize();
- }
-
- public synchronized void clear() {
- Object[] entries;
- synchronized (this) {
- entries = cache.values().toArray();
- cache.clear();
- }
- for (Object o : entries) {
- @SuppressWarnings("unchecked")
- Entry e = (Entry) o;
- V v = e.ref.get();
- e.ref.clear();
- cleanup(e);
- disposeValue(v);
- }
- }
-
- @Override
- public void put(final K k, V v, long holdTime, TimeUnit unit) {
- Entry e = new Entry(k, v, holdTime, unit);
- synchronized (this) {
- // First dispose of a previous entry.
- dispose(k);
- // Then cache the new one.
- cache.put(k, e);
-
- if (unit != null && holdTime > 0) {
- schedule(e);
- }
- }
- }
-
- @Override
- public V release(K k) {
- Entry e;
- synchronized (this) {
- e = cache.remove(k);
- }
- if (e == null)
- return null;
- return cleanup(e);
- }
-
- private V cleanup(Entry e) {
- if (e.future != null) {
- if (!e.future.isCancelled()) {
- boolean ret = e.future.cancel(false);
- if (ret == false)
- // Already disposing of this cached entry, let it be.
- return null;
- }
- }
- return e.ref.get();
- }
-
- private void dispose(K k) {
- Entry e;
- synchronized (this) {
- e = cache.remove(k);
- }
- if (e == null)
- // Has been released.
- return;
-
- V v = e.ref.get();
- if (v != null) {
- if (e.future != null)
- e.future.cancel(false);
- e.ref.clear();
- disposeValue(v);
- }
- }
-
- void schedule(final Entry e) {
- e.future = ThreadUtils.getNonBlockingWorkExecutor().schedule(new Runnable() {
- @Override
- public void run() {
- // Disposal may block, must transfer to blocking work executor.
- ThreadUtils.getBlockingWorkExecutor().execute(new Runnable() {
- @Override
- public void run() {
- dispose(e.key);
- }
- });
- }
- }, e.holdTime, e.unit);
- }
-
-
- /**
- * Override to customize disposal of values when their timer elapses.
- *
- * @param v the value to dispose of
- */
- protected void disposeValue(V v) {
- // Do nothing by default.
- }
-
- public class CacheEntry {
- private final Entry e;
- private final V value;
- public CacheEntry(Entry e) {
- this.e = e;
- this.value = e.ref.get();
- }
- public K getKey() {
- return e.key;
- }
- public V getValue() {
- return value;
- }
- public boolean disposeScheduled() {
- return e.future != null;
- }
- public void schedule(long holdTime, TimeUnit unit) {
- if (e.future == null) {
- e.holdTime = holdTime;
- e.unit = unit;
- SoftTimedCache.this.schedule(e);
- }
- }
- }
-
- public Collection getEntries() {
- ArrayList result = new ArrayList();
- synchronized (this) {
- for (Entry e : cache.values()) {
- result.add(new CacheEntry(e));
- }
- }
- return result;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.utils.datastructures.cache;
+
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.simantics.utils.threads.ThreadUtils;
+
+/**
+ * A timed (Key, Value) cache which disposes the cached entry after the
+ * specified amount of time if it is not removed from the cache. The hold time
+ * is given to the {@link #put(Object, Object, long)} method, separately for
+ * each value.
+ *
+ *
+ * The cached values are held as soft references, which makes them collectible
+ * under memory pressure, even before their hold time has ran out.
+ *
+ * @author Tuukka Lehtonen
+ *
+ * @param key type, held by strong references
+ * @param value type, held by soft references to allow collection of the
+ * cached elements when under memory pressure
+ */
+public class SoftTimedCache implements ITimedCache {
+
+ protected class Entry {
+ final K key;
+ final SoftReference ref;
+ long holdTime;
+ TimeUnit unit;
+
+ ScheduledFuture> future;
+
+ Entry(K k, V v, long holdTime, TimeUnit unit) {
+ assert k != null;
+ assert v != null;
+
+ this.key = k;
+ this.ref = new SoftReference(v);
+ this.holdTime = holdTime;
+ this.unit = unit;
+ }
+ }
+
+ private final Map cache = Collections.synchronizedMap(new HashMap());
+
+ @SuppressWarnings("unused")
+ private String name;
+
+ private Timer timer;
+
+ public SoftTimedCache() {
+ this("Cache Timer");
+ }
+
+ public SoftTimedCache(String name) {
+ this.name = name;
+ }
+
+ public int size() {
+ return cache.size();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (timer != null) {
+ timer.cancel();
+ }
+ clear();
+ super.finalize();
+ }
+
+ public synchronized void clear() {
+ Object[] entries;
+ synchronized (this) {
+ entries = cache.values().toArray();
+ cache.clear();
+ }
+ for (Object o : entries) {
+ @SuppressWarnings("unchecked")
+ Entry e = (Entry) o;
+ V v = e.ref.get();
+ e.ref.clear();
+ cleanup(e);
+ disposeValue(v);
+ }
+ }
+
+ @Override
+ public void put(final K k, V v, long holdTime, TimeUnit unit) {
+ Entry e = new Entry(k, v, holdTime, unit);
+ synchronized (this) {
+ // First dispose of a previous entry.
+ dispose(k);
+ // Then cache the new one.
+ cache.put(k, e);
+
+ if (unit != null && holdTime > 0) {
+ schedule(e);
+ }
+ }
+ }
+
+ @Override
+ public V release(K k) {
+ Entry e;
+ synchronized (this) {
+ e = cache.remove(k);
+ }
+ if (e == null)
+ return null;
+ return cleanup(e);
+ }
+
+ private V cleanup(Entry e) {
+ if (e.future != null) {
+ if (!e.future.isCancelled()) {
+ boolean ret = e.future.cancel(false);
+ if (ret == false)
+ // Already disposing of this cached entry, let it be.
+ return null;
+ }
+ }
+ return e.ref.get();
+ }
+
+ private void dispose(K k) {
+ Entry e;
+ synchronized (this) {
+ e = cache.remove(k);
+ }
+ if (e == null)
+ // Has been released.
+ return;
+
+ V v = e.ref.get();
+ if (v != null) {
+ if (e.future != null)
+ e.future.cancel(false);
+ e.ref.clear();
+ disposeValue(v);
+ }
+ }
+
+ void schedule(final Entry e) {
+ e.future = ThreadUtils.getNonBlockingWorkExecutor().schedule(new Runnable() {
+ @Override
+ public void run() {
+ // Disposal may block, must transfer to blocking work executor.
+ ThreadUtils.getBlockingWorkExecutor().execute(new Runnable() {
+ @Override
+ public void run() {
+ dispose(e.key);
+ }
+ });
+ }
+ }, e.holdTime, e.unit);
+ }
+
+
+ /**
+ * Override to customize disposal of values when their timer elapses.
+ *
+ * @param v the value to dispose of
+ */
+ protected void disposeValue(V v) {
+ // Do nothing by default.
+ }
+
+ public class CacheEntry {
+ private final Entry e;
+ private final V value;
+ public CacheEntry(Entry e) {
+ this.e = e;
+ this.value = e.ref.get();
+ }
+ public K getKey() {
+ return e.key;
+ }
+ public V getValue() {
+ return value;
+ }
+ public boolean disposeScheduled() {
+ return e.future != null;
+ }
+ public void schedule(long holdTime, TimeUnit unit) {
+ if (e.future == null) {
+ e.holdTime = holdTime;
+ e.unit = unit;
+ SoftTimedCache.this.schedule(e);
+ }
+ }
+ }
+
+ public Collection getEntries() {
+ ArrayList result = new ArrayList();
+ synchronized (this) {
+ for (Entry e : cache.values()) {
+ result.add(new CacheEntry(e));
+ }
+ }
+ return result;
+ }
+
+}