]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.runtime / src / org / simantics / scl / runtime / chr / FactActivationQueue.java
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java
new file mode 100644 (file)
index 0000000..05b410d
--- /dev/null
@@ -0,0 +1,120 @@
+package org.simantics.scl.runtime.chr;\r
+\r
+import java.util.Arrays;\r
+\r
+public class FactActivationQueue {\r
+    public static final boolean TRACE = false;\r
+    \r
+    private final PriorityContainer[] containers;\r
+    private PriorityContainer[] activeContainers = new PriorityContainer[8];\r
+    private int activeContainerCount; \r
+\r
+    public FactActivationQueue(int priorityCount) {\r
+        if(TRACE)\r
+            System.out.println("priorityCount = " + priorityCount);\r
+        containers = new PriorityContainer[priorityCount];\r
+        for(int i=0;i<priorityCount;++i)\r
+            containers[i] = new PriorityContainer(i); \r
+    }\r
+    \r
+    /**\r
+     * Adds a new fact with a given priority\r
+     */\r
+    public void add(int priority, Fact item) {\r
+        if(TRACE)\r
+            System.out.println("FactActivationQueue.add " + priority + "@" + item);\r
+        PriorityContainer container = containers[priority];\r
+        if(container.size == 0)\r
+            activateContainer(container);\r
+        container.push(item);\r
+    }\r
+    \r
+    private void activateContainer(PriorityContainer container) {\r
+        if(TRACE)\r
+            System.out.println("FactActivationQueue.activate priority " + container.priority);\r
+        if(activeContainers.length == activeContainerCount)\r
+            activeContainers = Arrays.copyOf(activeContainers, activeContainerCount*2);\r
+        adjustUpwards(activeContainerCount, container);\r
+        ++activeContainerCount;\r
+    }\r
+\r
+    private void deactivateContainer() {\r
+        --activeContainerCount;\r
+        adjustDownwards(0, activeContainers[activeContainerCount]);\r
+        activeContainers[activeContainerCount] = null;\r
+    }\r
+\r
+    private void adjustDownwards(int pos, PriorityContainer item) {\r
+        int priority = item.priority;\r
+        while(true) {\r
+            int npos = 2*pos+1;\r
+            if(npos+1 >= activeContainerCount) {\r
+                if(npos >= activeContainerCount)\r
+                    break;\r
+                PriorityContainer item1 = activeContainers[npos];\r
+                if(priority > item1.priority) {\r
+                    activeContainers[pos] = item1;\r
+                    activeContainers[npos] = item;\r
+                    return;\r
+                }\r
+                else\r
+                    break;\r
+            }\r
+            PriorityContainer item1 = activeContainers[npos];\r
+            PriorityContainer item2 = activeContainers[npos+1];\r
+            if(priority < item1.priority) {\r
+                if(priority < item2.priority)\r
+                    break;\r
+            }\r
+            else {\r
+                if(item1.priority < item2.priority) {\r
+                    activeContainers[pos] = item1;\r
+                    pos = npos;\r
+                    continue;\r
+                }\r
+            }\r
+            activeContainers[pos] = item2;\r
+            pos = npos+1;\r
+        }\r
+        activeContainers[pos] = item;\r
+    }\r
+\r
+    private void adjustUpwards(int pos, PriorityContainer item) {\r
+        int priority = item.priority;\r
+        while(pos > 0) {\r
+            int npos = (pos-1)/2;\r
+            PriorityContainer item1 = activeContainers[npos];\r
+            if(item1.priority > priority) {\r
+                activeContainers[pos] = item1;\r
+                pos = npos;\r
+            }\r
+            else\r
+                break;\r
+        }\r
+        activeContainers[pos] = item;\r
+    }\r
+    \r
+    /**\r
+     * Activates all facts with priority less than the current priority\r
+     */\r
+    public void activate(Object context, int currentPriority) {\r
+        if(TRACE)\r
+            System.out.println("FactActivationQueue.activate " + currentPriority);\r
+        while(activeContainerCount > 0) {\r
+            PriorityContainer topContainer = activeContainers[0];\r
+            int priority = topContainer.priority;\r
+            if(priority >= currentPriority)\r
+                return;\r
+            \r
+            Fact fact = topContainer.pop();\r
+            if(topContainer.size == 0)\r
+                deactivateContainer();\r
+            \r
+            int newPriority = fact.activate(context, priority);\r
+            if(TRACE)\r
+                System.out.println("    [" + currentPriority + "] " + fact + " oldPriority=" + priority + ", newPriority=" + newPriority);\r
+            if(newPriority >= 0)\r
+                add(newPriority, fact);\r
+        }\r
+    }\r
+}\r