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