--- /dev/null
+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