Browse Source

Merge branch 'GC' into yentl

Yentl Van Tendeloo 9 years ago
parent
commit
cb3c8b1c87

+ 10 - 2
bootstrap/modelling.alc

@@ -4,6 +4,8 @@ include "object_operations.alh"
 include "constructors.alh"
 include "metamodels.alh"
 
+Element global_models = ?
+
 String function instantiated_name(element : Element, original : String):
 	if (original == ""):
 		return "__" + cast_id2s(element)
@@ -369,7 +371,10 @@ Void function construct_model():
 	while (True):
 		command = input()
 		if (command == "instantiate_bottom"):
-			output(instantiate_bottom())
+			Element m
+			m = instantiate_bottom()
+			set_add(global_models, m)
+			output(m)
 		elif (command == "add_node"):
 			model_add_node(input(), input())
 		elif (command == "add_value"):
@@ -383,7 +388,10 @@ Void function construct_model():
 		elif (command == "retype"):
 			retype(input(), input(), input())
 		elif (command == "instantiate_model"):
-			output(instantiate_model(input()))
+			Element m
+			m = instantiate_model(input())
+			set_add(global_models, m)
+			output(m)
 		elif (command == "instantiate_node"):
 			instantiate_node(input(), input(), input())
 		elif (command == "instantiate_attribute"):

+ 5 - 1
hybrid_server/classes/mvkcontroller.xml

@@ -7,6 +7,8 @@
         <body>
             <![CDATA[
             self.mvs = ModelverseState("../bootstrap/bootstrap.m")
+            # Enable Garbage Collection
+            self.mvs.GC = True
             self.root = self.mvs.read_root()[0]
             self.mvk = ModelverseKernel(self.root)
             self.all_failed = False
@@ -155,7 +157,9 @@
                                             self.destination = self.output_queue[user].pop(0)
                                             self.value = self.mvk.returnvalue
                                             self.all_failed = False
+
                             else:
+                                self.mvs.garbage_collect()
                                 out = self.mvs.read_outgoing(self.root)[0]
                                 for m in out:
                                     src, user = self.mvs.read_edge(m)[0]
@@ -177,7 +181,7 @@
                         </raise>
                     </transition>
 
-                    <transition cond="self.timeout and self.destination is None" after="self.sccd_yield() + 0.05" target="."/>
+                    <transition cond="self.timeout and self.destination is None" after="self.sccd_yield() + 0.10" target="."/>
 
                     <transition cond="not self.timeout and self.destination is None" after="self.sccd_yield()" target="."/>
                 </state>

+ 2 - 2
kernel/modelverse_kernel/main.py

@@ -61,7 +61,7 @@ class ModelverseKernel(object):
             raise Exception("Instruction pointer could not be found!")
         elif isinstance(phase_v, string_types):
             if phase_v == "init" and inst in self.compiled:
-                #print("%-30s(%s)" % ("COMPILED " + str(self.primitives[inst]), phase_v))
+                #print("%-30s(%s)" % ("COMPILED " + str(self.compiled[inst]), phase_v))
                 gen = self.execute_primitive(user_root, inst, username)
             elif inst_v is None:
                 raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info, inst_v, phase_v))
@@ -441,7 +441,6 @@ class ModelverseKernel(object):
                                    ("RDE", [user_frame, "returnvalue"]),
                                    ("CNV", ["finish"]),
                                   ]
-        print("Resolved to " + str(variable))
         _, _, _, _ =        yield [("CD", [user_frame, "phase", new_phase]),
                                    ("CD", [user_frame, "returnvalue", variable]),
                                    ("DE", [phase_link]),
@@ -874,6 +873,7 @@ class ModelverseKernel(object):
                               ]
 
         if value is not None:
+            v =         yield [("RV", [value])]
             _, _, finish = \
                         yield [("CD", [user_frame, "returnvalue", value]),
                                ("CD", [user_root, "input", next]),

+ 1 - 1
scripts/make_all.py

@@ -17,4 +17,4 @@ if __name__ == "__main__":
         for f in files:
             do_compile(address, f, str(random.random()), f, "CO")
 
-        link_and_load(address, username, files, False)
+        link_and_load(address, username, files)

+ 30 - 8
state/modelverse_state/main.py

@@ -28,6 +28,8 @@ class ModelverseState(object):
         self.incoming = defaultdict(set)
         self.values = {}
         self.nodes = set()
+        self.GC = True
+        self.to_delete = set()
 
         self.cache = {}
 
@@ -315,10 +317,20 @@ class ModelverseState(object):
             return ([self.edges[e][0] for e in matches], status.SUCCESS)
 
     def delete_node(self, node):
+        if node is self.root:
+            return (None, status.FAIL_DN_UNKNOWN)
+
         if node not in self.nodes:
             return (None, status.FAIL_DN_UNKNOWN)
 
         self.nodes.remove(node)
+
+        if node in self.cache:
+            del self.cache[node]
+
+        if node in self.values:
+            del self.values[node]
+
         s = set()
         for e in self.outgoing[node]:
             s.add(e)
@@ -326,10 +338,9 @@ class ModelverseState(object):
             s.add(e)
         for e in s:
             self.delete_edge(e)
-        if node in self.outgoing:
-            del self.outgoing[node]
-        if node in self.incoming:
-            del self.incoming[node]
+
+        del self.outgoing[node]
+        del self.incoming[node]
         return (None, status.SUCCESS)
 
     def delete_edge(self, edge):
@@ -339,6 +350,7 @@ class ModelverseState(object):
         s, t = self.edges[edge]
         self.incoming[t].remove(edge)
         self.outgoing[s].remove(edge)
+
         del self.edges[edge]
 
         s = set()
@@ -348,9 +360,19 @@ class ModelverseState(object):
             s.add(e)
         for e in s:
             self.delete_edge(e)
-        if edge in self.outgoing:
-            del self.outgoing[edge]
-        if edge in self.incoming:
-            del self.incoming[edge]
+        del self.outgoing[edge]
+        del self.incoming[edge]
+
+        if (self.GC) and (not self.incoming[t]) and (t not in self.edges):
+            # Remove this node as well
+            # Edges aren't deleted like this, as they might have a reachable target and source!
+            # If they haven't, they will be removed because the source was removed.
+            self.to_delete.add(t)
 
         return (None, status.SUCCESS)
+
+    def garbage_collect(self):  
+        while self.to_delete:
+            t = self.to_delete.pop()
+            if not self.incoming[t]:
+                self.delete_node(t)