-package org.simantics.modeling.ui.diagramEditor;\r
-\r
-import gnu.trove.map.hash.TObjectLongHashMap;\r
-\r
-import java.util.ArrayDeque;\r
-\r
-import org.eclipse.swt.widgets.Display;\r
-\r
-\r
-public class DisposingPolicy {\r
- \r
- public static final boolean DEBUG = false;\r
- \r
- public static final int MAX_QUEUE_LENGTH = 8;\r
- public static final long DISPOSE_TIME = 30000L; // ms\r
- public static final long MIN_DELAY = 200L; // ms\r
- \r
- private ArrayDeque<Runnable> disposerQueue = new ArrayDeque<Runnable>(MAX_QUEUE_LENGTH);\r
- private TObjectLongHashMap<Runnable> disposeTime =\r
- new TObjectLongHashMap<Runnable>(MAX_QUEUE_LENGTH);\r
- private Runnable currentlyScheduled = null;\r
- \r
- private Runnable disposeOne = new Runnable() {\r
- @Override\r
- public void run() {\r
- if(!disposerQueue.isEmpty()) {\r
- Runnable runnable = disposerQueue.removeFirst();\r
- disposeTime.remove(runnable);\r
- currentlyScheduled = null;\r
- runnable.run();\r
- if(DEBUG)\r
- System.out.println("Executed disposer " + runnable);\r
- if(!disposerQueue.isEmpty())\r
- scheduleDispose();\r
- }\r
- }\r
- };\r
- \r
- private void scheduleDispose() {\r
- currentlyScheduled = disposerQueue.peekFirst();\r
- long delay = Math.max(\r
- disposeTime.get(currentlyScheduled) - System.currentTimeMillis(),\r
- MIN_DELAY);\r
- Display.getCurrent().timerExec((int)delay, disposeOne);\r
- if(DEBUG)\r
- System.out.println("Scheduled disposer " + currentlyScheduled + " in " + delay + " ms");\r
- }\r
- \r
- /**\r
- * Runs the disposer either after DISPOSE_TIME or when there are\r
- * more than MAX_QUEUE_LENGTH disposers active and this is first\r
- * of them (by activation order). This method must be called from\r
- * UI thread.\r
- */\r
- public void addDisposer(Runnable disposer) {\r
- if(DEBUG)\r
- System.out.println("Added disposer " + disposer);\r
- if(disposeTime.contains(disposer))\r
- return;\r
- if(disposerQueue.size() >= MAX_QUEUE_LENGTH)\r
- disposeOne.run();\r
- disposerQueue.addLast(disposer);\r
- disposeTime.put(disposer, System.currentTimeMillis()+DISPOSE_TIME);\r
- if(disposerQueue.size() == 1)\r
- scheduleDispose();\r
- }\r
- \r
- /**\r
- * Cancels a disposer added before. This method must be called from\r
- * UI thread.\r
- */\r
- public void removeDisposer(Runnable disposer) {\r
- if(DEBUG)\r
- System.out.println("Removed disposer " + disposer);\r
- disposerQueue.remove(disposer);\r
- disposeTime.remove(disposer);\r
- if(disposer == currentlyScheduled) {\r
- currentlyScheduled = null;\r
- if(!disposerQueue.isEmpty())\r
- scheduleDispose();\r
- }\r
- }\r
- \r
-}\r
+package org.simantics.modeling.ui.diagramEditor;
+
+import gnu.trove.map.hash.TObjectLongHashMap;
+
+import java.util.ArrayDeque;
+
+import org.eclipse.swt.widgets.Display;
+
+
+public class DisposingPolicy {
+
+ public static final boolean DEBUG = false;
+
+ public static final int MAX_QUEUE_LENGTH = 8;
+ public static final long DISPOSE_TIME = 30000L; // ms
+ public static final long MIN_DELAY = 200L; // ms
+
+ private volatile int maxQueueLength;
+ private ArrayDeque<Runnable> disposerQueue;
+ private TObjectLongHashMap<Runnable> disposeTime;
+ private Runnable currentlyScheduled = null;
+
+ private Runnable disposeOne = () -> {
+ if(!disposerQueue.isEmpty()) {
+ Runnable runnable = disposerQueue.removeFirst();
+ disposeTime.remove(runnable);
+ currentlyScheduled = null;
+ runnable.run();
+ if(DEBUG)
+ System.out.println("Executed disposer " + runnable);
+ if(!disposerQueue.isEmpty())
+ scheduleDispose();
+ }
+ };
+
+ public DisposingPolicy() {
+ this(MAX_QUEUE_LENGTH);
+ }
+
+ public DisposingPolicy(int maxQueueLength) {
+ this.maxQueueLength = maxQueueLength;
+ this.disposerQueue = new ArrayDeque<>(maxQueueLength);
+ this.disposeTime = new TObjectLongHashMap<>(maxQueueLength);
+ }
+
+ public void setMaxQueueLength(int maxQueueLength) {
+ this.maxQueueLength = maxQueueLength;
+ }
+
+ private void scheduleDispose() {
+ currentlyScheduled = disposerQueue.peekFirst();
+ long delay = Math.max(
+ disposeTime.get(currentlyScheduled) - System.currentTimeMillis(),
+ MIN_DELAY);
+ Display.getCurrent().timerExec((int)delay, disposeOne);
+ if(DEBUG)
+ System.out.println("Scheduled disposer " + currentlyScheduled + " in " + delay + " ms");
+ }
+
+ /**
+ * Runs the disposer either after DISPOSE_TIME or when there are
+ * more than {@link #maxQueueLength} disposers active and this is first
+ * of them (by activation order). This method must be called from
+ * UI thread.
+ */
+ public void addDisposer(Runnable disposer) {
+ if(DEBUG)
+ System.out.println("Added disposer " + disposer);
+ if(disposeTime.contains(disposer))
+ return;
+ if(disposerQueue.size() >= maxQueueLength)
+ disposeOne.run();
+ disposerQueue.addLast(disposer);
+ disposeTime.put(disposer, System.currentTimeMillis()+DISPOSE_TIME);
+ if(disposerQueue.size() == 1)
+ scheduleDispose();
+ }
+
+ /**
+ * Cancels a disposer added before. This method must be called from
+ * UI thread.
+ */
+ public void removeDisposer(Runnable disposer) {
+ if(DEBUG)
+ System.out.println("Removed disposer " + disposer);
+ disposerQueue.remove(disposer);
+ disposeTime.remove(disposer);
+ if(disposer == currentlyScheduled) {
+ currentlyScheduled = null;
+ if(!disposerQueue.isEmpty())
+ scheduleDispose();
+ }
+ }
+
+}