]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DisposingPolicy.java
Allow changing DisposingPolicy max queue length
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / DisposingPolicy.java
1 package org.simantics.modeling.ui.diagramEditor;
2
3 import gnu.trove.map.hash.TObjectLongHashMap;
4
5 import java.util.ArrayDeque;
6
7 import org.eclipse.swt.widgets.Display;
8
9
10 public class DisposingPolicy {
11
12     public static final boolean DEBUG = false;
13
14     public static final int MAX_QUEUE_LENGTH = 8;
15     public static final long DISPOSE_TIME = 30000L; // ms
16     public static final long MIN_DELAY = 200L; // ms
17
18     private volatile int maxQueueLength;
19     private ArrayDeque<Runnable> disposerQueue;
20     private TObjectLongHashMap<Runnable> disposeTime;
21     private Runnable currentlyScheduled = null;
22
23     private Runnable disposeOne = () -> {
24         if(!disposerQueue.isEmpty()) {
25             Runnable runnable = disposerQueue.removeFirst();
26             disposeTime.remove(runnable);
27             currentlyScheduled = null;
28             runnable.run();
29             if(DEBUG)
30                 System.out.println("Executed disposer " + runnable);
31             if(!disposerQueue.isEmpty())
32                 scheduleDispose();
33         }
34     };
35
36     public DisposingPolicy() {
37         this(MAX_QUEUE_LENGTH);
38     }
39
40     public DisposingPolicy(int maxQueueLength) {
41         this.maxQueueLength = maxQueueLength;
42         this.disposerQueue = new ArrayDeque<>(maxQueueLength);
43         this.disposeTime = new TObjectLongHashMap<>(maxQueueLength);
44     }
45
46     public void setMaxQueueLength(int maxQueueLength) {
47         this.maxQueueLength = maxQueueLength;
48     }
49
50     private void scheduleDispose() {
51         currentlyScheduled = disposerQueue.peekFirst();
52         long delay = Math.max(
53                 disposeTime.get(currentlyScheduled) - System.currentTimeMillis(),
54                 MIN_DELAY);
55         Display.getCurrent().timerExec((int)delay, disposeOne);
56         if(DEBUG)
57             System.out.println("Scheduled disposer " + currentlyScheduled + " in " + delay + " ms");
58     }
59
60     /**
61      * Runs the disposer either after DISPOSE_TIME or when there are
62      * more than {@link #maxQueueLength} disposers active and this is first
63      * of them (by activation order). This method must be called from
64      * UI thread.
65      */
66     public void addDisposer(Runnable disposer) {
67         if(DEBUG)
68             System.out.println("Added disposer " + disposer);
69         if(disposeTime.contains(disposer))
70             return;
71         if(disposerQueue.size() >= maxQueueLength)
72             disposeOne.run();
73         disposerQueue.addLast(disposer);
74         disposeTime.put(disposer, System.currentTimeMillis()+DISPOSE_TIME);
75         if(disposerQueue.size() == 1)
76             scheduleDispose();
77     }
78
79     /**
80      * Cancels a disposer added before. This method must be called from
81      * UI thread.
82      */
83     public void removeDisposer(Runnable disposer) {
84         if(DEBUG)
85             System.out.println("Removed disposer " + disposer);
86         disposerQueue.remove(disposer);
87         disposeTime.remove(disposer);
88         if(disposer == currentlyScheduled) {
89             currentlyScheduled = null;
90             if(!disposerQueue.isEmpty())
91                 scheduleDispose();
92         }
93     }
94
95 }