]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.runtime / src / org / simantics / scl / runtime / chr / FactActivationQueue.java
1 package org.simantics.scl.runtime.chr;\r
2 \r
3 import java.util.Arrays;\r
4 \r
5 public class FactActivationQueue {\r
6     public static final boolean TRACE = false;\r
7     \r
8     private final PriorityContainer[] containers;\r
9     private PriorityContainer[] activeContainers = new PriorityContainer[8];\r
10     private int activeContainerCount; \r
11 \r
12     public FactActivationQueue(int priorityCount) {\r
13         if(TRACE)\r
14             System.out.println("priorityCount = " + priorityCount);\r
15         containers = new PriorityContainer[priorityCount];\r
16         for(int i=0;i<priorityCount;++i)\r
17             containers[i] = new PriorityContainer(i); \r
18     }\r
19     \r
20     /**\r
21      * Adds a new fact with a given priority\r
22      */\r
23     public void add(int priority, Fact item) {\r
24         if(TRACE)\r
25             System.out.println("FactActivationQueue.add " + priority + "@" + item);\r
26         PriorityContainer container = containers[priority];\r
27         if(container.size == 0)\r
28             activateContainer(container);\r
29         container.push(item);\r
30     }\r
31     \r
32     private void activateContainer(PriorityContainer container) {\r
33         if(TRACE)\r
34             System.out.println("FactActivationQueue.activate priority " + container.priority);\r
35         if(activeContainers.length == activeContainerCount)\r
36             activeContainers = Arrays.copyOf(activeContainers, activeContainerCount*2);\r
37         adjustUpwards(activeContainerCount, container);\r
38         ++activeContainerCount;\r
39     }\r
40 \r
41     private void deactivateContainer() {\r
42         --activeContainerCount;\r
43         adjustDownwards(0, activeContainers[activeContainerCount]);\r
44         activeContainers[activeContainerCount] = null;\r
45     }\r
46 \r
47     private void adjustDownwards(int pos, PriorityContainer item) {\r
48         int priority = item.priority;\r
49         while(true) {\r
50             int npos = 2*pos+1;\r
51             if(npos+1 >= activeContainerCount) {\r
52                 if(npos >= activeContainerCount)\r
53                     break;\r
54                 PriorityContainer item1 = activeContainers[npos];\r
55                 if(priority > item1.priority) {\r
56                     activeContainers[pos] = item1;\r
57                     activeContainers[npos] = item;\r
58                     return;\r
59                 }\r
60                 else\r
61                     break;\r
62             }\r
63             PriorityContainer item1 = activeContainers[npos];\r
64             PriorityContainer item2 = activeContainers[npos+1];\r
65             if(priority < item1.priority) {\r
66                 if(priority < item2.priority)\r
67                     break;\r
68             }\r
69             else {\r
70                 if(item1.priority < item2.priority) {\r
71                     activeContainers[pos] = item1;\r
72                     pos = npos;\r
73                     continue;\r
74                 }\r
75             }\r
76             activeContainers[pos] = item2;\r
77             pos = npos+1;\r
78         }\r
79         activeContainers[pos] = item;\r
80     }\r
81 \r
82     private void adjustUpwards(int pos, PriorityContainer item) {\r
83         int priority = item.priority;\r
84         while(pos > 0) {\r
85             int npos = (pos-1)/2;\r
86             PriorityContainer item1 = activeContainers[npos];\r
87             if(item1.priority > priority) {\r
88                 activeContainers[pos] = item1;\r
89                 pos = npos;\r
90             }\r
91             else\r
92                 break;\r
93         }\r
94         activeContainers[pos] = item;\r
95     }\r
96     \r
97     /**\r
98      * Activates all facts with priority less than the current priority\r
99      */\r
100     public void activate(Object context, int currentPriority) {\r
101         if(TRACE)\r
102             System.out.println("FactActivationQueue.activate " + currentPriority);\r
103         while(activeContainerCount > 0) {\r
104             PriorityContainer topContainer = activeContainers[0];\r
105             int priority = topContainer.priority;\r
106             if(priority >= currentPriority)\r
107                 return;\r
108             \r
109             Fact fact = topContainer.pop();\r
110             if(topContainer.size == 0)\r
111                 deactivateContainer();\r
112             \r
113             int newPriority = fact.activate(context, priority);\r
114             if(TRACE)\r
115                 System.out.println("    [" + currentPriority + "] " + fact + " oldPriority=" + priority + ", newPriority=" + newPriority);\r
116             if(newPriority >= 0)\r
117                 add(newPriority, fact);\r
118         }\r
119     }\r
120 }\r