Parcourir la source

Working sleep that is less busy loop

Yentl Van Tendeloo il y a 8 ans
Parent
commit
f5dba6a3dc

+ 0 - 1
bootstrap/bootstrap.py

@@ -105,7 +105,6 @@ def bootstrap():
                     "log": ["String", "String"],
                     "time": ["Float"],
                     "hash": ["String", "String"],
-                    "__sleep": ["Float", "Float"],
                 }
 
     jit_primitives = {

+ 0 - 56
bootstrap/core_algorithm.alc

@@ -1744,56 +1744,6 @@ String function cmd_service_register(user_id : String, service_name : String):
 	else:
 		return "Service already exists: " + service_name!
 
-String function cmd_user_password(user_id : String, user_name : String, new_password : String):
-	if (bool_or(user_id == get_user_id(user_name), is_admin(user_id))):
-		if (get_user_id(user_name) != ""):
-			instantiate_attribute(core, get_user_id(user_name), "password", hash(new_password))
-			return "Success"!
-		else:
-			return "No such user: " + user_name!
-	else:
-		return "Permission denied to user: " + user_name!
-
-String function cmd_transformation_signature(user_id : String, transformation_name : String):
-	String model_id
-	model_id = get_model_id(transformation_name)
-
-	if (model_id != ""):
-		if (is_nominal_instance(core, model_id, "Transformation")):
-			if (allow_read(user_id, transformation_name)):
-				String result
-				String elem
-				Element inputs
-				Element outputs
-
-				result = "Success: "
-				inputs = allOutgoingAssociationInstances(core, model_id, "transformInput")
-				while (read_nr_out(inputs) > 0):
-					elem = set_pop(inputs)
-					result = string_join(string_join(string_join(string_join("I ", read_attribute(core, elem, "name")), " "), read_attribute(core, readAssociationDestination(core, elem), "name")), "\n")
-
-				outputs = allOutgoingAssociationInstances(core, model_id, "transformOutput")
-				while (read_nr_out(outputs) > 0):
-					elem = set_pop(outputs)
-					result = string_join(string_join(string_join(string_join("O ", read_attribute(core, elem, "name")), " "), read_attribute(core, readAssociationDestination(core, elem), "name")), "\n")
-
-				return result!
-			else:
-				return "Permission denied to transformation: " + transformation_name!
-		else:
-			return "Model is not a transformation: " + transformation_name!
-	else:
-		return "No such transformation: " + transformation_name!
-	
-String function cmd_element_list_nice(user_id : String, model_name : String):
-	if (get_model_id(model_name) != ""):
-		if (allow_read(user_id, get_model_id(model_name))):
-			return "Success: " + JSON_print(get_full_model(get_model_id(model_name)))!
-		else:
-			return "Permission denied to model: " + model_name!
-	else:
-		return "No such model: " + model_name!
-
 Void function user_function_skip_init(user_id : String):
 	String cmd
 	String result
@@ -1865,12 +1815,6 @@ Void function user_function_skip_init(user_id : String):
 			output(cmd_admin_demote(user_id, single_input("User name?")))
 		elif (cmd == "service_register"):
 			output(cmd_service_register(user_id, single_input("Service name?")))
-		elif (cmd == "user_password"):
-			output(cmd_user_password(user_id, single_input("User name?"), single_input("New password?")))
-		elif (cmd == "transformation_read_signature"):
-			output(cmd_transformation_signature(user_id, single_input("Transformation name?")))
-		elif (cmd == "element_list_nice"):
-			output(cmd_element_list_nice(user_id, single_input("Model name?")))
 		elif (cmd == "verbose"):
 			set_verbose(True)
 		elif (cmd == "quiet"):

+ 2 - 19
bootstrap/mini_modify.alc

@@ -222,8 +222,8 @@ String function cmd_read_outgoing(model : Element, element_name : String, type :
 	String result
 	Element elems
 
+	result = "Success: "
 	if (dict_in(model["model"], element_name)):
-		result = "Success: "
 		elems = allOutgoingAssociationInstances(model, element_name, type)
 		while (read_nr_out(elems) > 0):
 			result = string_join(result, set_pop(elems)) + "\n"
@@ -235,8 +235,8 @@ String function cmd_read_incoming(model : Element, element_name : String, type :
 	String result
 	Element elems
 
+	result = "Success: "
 	if (dict_in(model["model"], element_name)):
-		result = "Success: "
 		elems = allIncomingAssociationInstances(model, element_name, type)
 		while (read_nr_out(elems) > 0):
 			result = string_join(result, set_pop(elems)) + "\n"
@@ -244,21 +244,6 @@ String function cmd_read_incoming(model : Element, element_name : String, type :
 	else:
 		return "Element not found: " + element_name!
 
-String function cmd_connections_between(model : Element, source_name : String, target_name : String):
-	String result
-	Element options
-
-	if (dict_in(model["model"], source_name)):
-		if (dict_in(model["model"], target_name)):
-			result = "Success: "
-			options = allowedAssociationsBetween(model, source_name, target_name)
-			while (read_nr_out(options) > 0):
-				result = string_join(result, set_pop(options)) + "\n"
-		else:
-			return ("Element not found: " + target_name)!
-	else:
-		return ("Element not found: " + source_name)!
-
 String function cmd_read(model : Element, element_name : String):
 	String result
 	Element attr_list
@@ -382,8 +367,6 @@ Element function modify(model : Element, write : Boolean):
 			output(cmd_read_association_source(write, model, single_input("Name?")))
 		elif (cmd == "read_association_destination"):
 			output(cmd_read_association_destination(write, model, single_input("Name?")))
-		elif (cmd == "connections_between"):
-			output(cmd_connections_between(model, single_input("Source element?"), single_input("Target element?")))
 		else:
 			output("Unknown command while modelling: " + cast_v2s(cmd))
 			output("Use command 'help' to get a list of available commands")

+ 6 - 14
bootstrap/model_management.alc

@@ -176,20 +176,18 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 			key = set_pop(keys)
 			type = read_type(model, key)
 
-			new_name = retyping_key + key
-
 			if (is_edge(model["model"][key])):
 				src = cast_id2s(read_edge_src(model["model"][key]))
 				dst = cast_id2s(read_edge_dst(model["model"][key]))
 				if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))):
-					new_name = instantiate_link(new_model, retyping_key + type, new_name, elem_map[src], elem_map[dst])
+					new_name = instantiate_link(new_model, retyping_key + type, "", elem_map[src], elem_map[dst])
 				else:
 					set_add(second_keys, key)
 					new_name = ""
 			elif (has_value(model["model"][key])):
-				new_name = instantiate_value(new_model, retyping_key + type, new_name, model["model"][key])
+				new_name = instantiate_value(new_model, retyping_key + type, "", model["model"][key])
 			else:
-				new_name = instantiate_node(new_model, retyping_key + type, new_name)
+				new_name = instantiate_node(new_model, retyping_key + type, "")
 
 			if (new_name != ""):
 				// Add the new name to a map which registers the mapping to the new name
@@ -255,7 +253,6 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 	String link
 	String src_name
 	String dst_name
-	String new_name
 
 	result = create_node()
 	tracability_model = instantiate_model(import_node("models/Tracability"))
@@ -309,11 +306,6 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 						set_add(second_keys, key)
 		else:
 			retyping_key = splitted[0]
-			if (read_nr_out(string_split(key, "/")) > 1):
-				new_name = list_read(string_split(key, "/"), 1)
-			else:
-				new_name = key
-			log("Create element " + new_name)
 
 			if (dict_in(result, retyping_key)):
 				original_type = splitted[1]
@@ -328,7 +320,7 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 						// Though we first check the model to which it was mapped, as this should be the same as we have now
 						if (bool_and(dict_in(result[retyping_key]["model"], mapping[src]), dict_in(result[retyping_key]["model"], mapping[dst]))):
 							// The matching worked fine
-							dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, new_name, mapping[src], mapping[dst]))
+							dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, key, mapping[src], mapping[dst]))
 						else:
 							log("ERROR mapping: source/target mapped to model, but not found in expected model; ignoring")
 					else:
@@ -337,11 +329,11 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 
 				elif (has_value(elem)):
 					// Has a value, so copy that as well
-					dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, new_name, elem))
+					dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, key, elem))
 
 				else:
 					// Is a node
-					dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, new_name))
+					dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, key))
 
 		if (read_nr_out(keys) == 0):
 			keys = second_keys

+ 0 - 5
bootstrap/primitives.alc

@@ -82,11 +82,6 @@ Boolean function is_physical_boolean(a: Element) = ?primitives/is_physical_boole
 Boolean function is_physical_action(a: Element) = ?primitives/is_physical_action
 Float function time() = ?primitives/time
 String function hash(a : String) = ?primitives/hash
-Float function __sleep(a : Float, b : Boolean) = ?primitives/__sleep
-
-Float function sleep(a : Float):
-	__sleep(a, False)
-	return a!
 
 Element function exec(first_instr : Element):
 	// This does very ugly things, so beware!

+ 8 - 0
bootstrap/utils.alc

@@ -54,6 +54,14 @@ String function JSON_print(model : Element):
 	result = result + "]"
 	return result!
 
+Void function sleep(timeout : Float):
+	// TODO Placeholder function for a real sleep operation
+	Float start
+	start = time()
+	while (time() < (start + timeout)):
+		continue!
+	return!
+
 Element function input_timeout(timeout : Float):
 	Float start
 	start = time()

+ 84 - 112
hybrid_server/classes/task.xml

@@ -11,11 +11,12 @@
             self.taskname = taskname
             self.mvs_operations = mvs_operations
             self.mvk = mvk
-            self.unlocked = True
 
-            self.input_queue = []
+            self.unlock_at = 0.0
+            self.failed = False
             self.output_queue = []
             self.outputs = []
+            self.do_yield = False
             ]]>
         </body>
 
@@ -37,27 +38,98 @@
                     if commands is None:
                         break
                     reply = [mvs_operations[command[0]](*(command[1])) for command in commands]
-                return (0.0, False)
+                self.unlock_at = 0.0
             except SleepKernel as e:
-                print("Got sleep for: " + str(e.timeout))
-                return (e.timeout, False)
+                self.unlock_at = time.time() + e.timeout
             except:
                 import traceback
                 print(traceback.format_exc())
-                return (float('inf'), False)
+                #TODO delete self, as the task has crashed!
+                return False
+            return True
             ]]>
         </body>
     </method>
 
-    <scxml initial="main">
-        <parallel id="main">
-            <state id="queue">
-                <state id="queue">
+    <scxml initial="start">
+        <parallel id="start">
+            <state id="execution" initial="running">
+                <state id="running" initial="executing">
+                    <transition event="pause_task" target="../suspended"/>
+
+                    <state id="executing">
+                        <onentry>
+                            <script>
+                                start_time = time.time()
+
+                                if start_time > self.unlock_at:
+                                    # Grant each task some milliseconds of execution
+                                    self.do_yield = False
+                                    while (time.time() - start_time &lt; 0.05):
+                                        if not self.execute_modelverse(self.taskname, "execute_rule", []):
+                                            # Failed!
+                                            self.failed = True
+                                            break
+
+                                        if not self.mvk.success:
+                                            # Blocking or broken, so quit already to stop wasting CPU
+                                            self.do_yield = True
+                                            break
+                                else:
+                                    self.do_yield = True
+
+                                if not self.failed:
+                                    # Perform output if there is anything
+                                    while self.output_queue:
+                                        if self.execute_modelverse(self.taskname, "get_output", []):
+                                            if self.mvk.success:
+                                                self.outputs.append((self.output_queue.pop(0), self.mvk.returnvalue))
+                                            else:
+                                                # No output left in Mv, so break
+                                                break
+                                        else:
+                                            self.failed = True
+                                            break
+                            </script>
+                        </onentry>
+
+                        <transition cond="self.failed" target="../../failed"/>
+                        <transition after="self.sccd_yield()" target="."/>
+                        <transition cond="self.do_yield" target="../yielded"/>
+                    </state>
+
+                    <state id="yielded">
+                        <transition after="self.sccd_yield() + (time.time() - self.unlock_at)" target="../executing"/>
+                        <transition event="processed_input" target="../executing"/>
+                        <transition event="waiting_output" target="../executing"/>
+                    </state>
+                </state>
+
+                <state id="suspended">
+                    <state id="suspended">
+                        <transition event="resume" target="../../running"/>
+                    </state>
+                </state>
+
+                <state id="failed">
+                    <state id="failed">
+                        <!-- TODO delete task -->
+                    </state>
+                </state>
+            </state>
+
+            <state id="process_events">
+                <state id="process_events">
                     <transition event="input" target=".">
                         <parameter name="params"/>
                         <script>
-                            self.input_queue.extend(params)
+                            for args_entry in params:
+                                if not self.execute_modelverse(self.taskname, "set_input", [args_entry]):
+                                    # Failed!
+                                    self.failed = True
+                                    break
                         </script>
+                        <raise event="processed_input"/>
                     </transition>
 
                     <transition event="output" target=".">
@@ -65,6 +137,7 @@
                         <script>
                             self.output_queue.append(params)
                         </script>
+                        <raise event="waiting_output"/>
                     </transition>
 
                     <transition cond="self.outputs" target=".">
@@ -77,107 +150,6 @@
                     </transition>
                 </state>
             </state>
-
-            <state id="process" initial="running">
-                <state id="running" initial="components">
-                    <transition event="suspend" target="../suspended"/>
-
-                    <history id="history" type="deep"/>
-
-                    <parallel id="components">
-                        <state id="input">
-                            <state id="input">
-                                <transition cond="self.input_queue" target=".">
-                                    <script>
-                                        for args_entry in self.input_queue:
-                                            self.execute_modelverse(self.taskname, "set_input", [args_entry])
-                                        self.input_queue = []
-                                    </script>
-                                    <raise event="wake_timer"/>
-                                </transition>
-                            </state>
-                        </state>
-
-                        <state id="processing" initial="processing">
-                            <state id="processing">
-                                <onentry>
-                                    <script>
-                                        start_time = time.time()
-                                        # Grant each task some milliseconds of execution
-                                        while (time.time() - start_time &lt; 0.05):
-                                            timeout = self.execute_modelverse(self.taskname, "execute_rule", [])
-                                            if timeout[0] > 0.0:
-                                                # We should not continue immediately
-                                                break
-                                        self.timeout = timeout
-                                    </script>
-                                </onentry>
-
-                                <transition cond="self.timeout[0] == 0.0" after="self.sccd_yield()" target="."/>
-                                <transition cond="0.0 &lt; self.timeout[0] &lt; float('inf')" after="self.sccd_yield()" target="../blocked">
-                                    <script>
-                                        self.unlocked = False
-                                    </script>
-                                    <raise event="start_timer">
-                                        <parameter expr="self.timeout[0]"/>
-                                        <parameter expr="self.timeout[1]"/>
-                                    </raise>
-                                </transition>
-                                <transition cond="self.timeout[0] == float('inf')" target="../failed"/>
-                            </state>
-
-                            <state id="blocked">
-                                <transition cond="self.unlocked" target="../processing"/>
-                            </state>
-
-                            <state id="failed">
-                                <script>
-                                    print("TODO: task has failed")
-                                </script>
-                            </state>
-                        </state>
-
-                        <state id="output">
-                            <state id="output">
-                                <onentry>
-                                    <script>
-                                        if self.output_queue:
-                                            if self.execute_modelverse(self.taskname, "get_output", []):
-                                                self.outputs.append((self.output_queue.pop(0), self.mvk.returnvalue))
-                                    </script>
-                                </onentry>
-                            </state>
-                        </state>
-                    </parallel>
-                </state>
-
-                <state id="suspended">
-                    <transition event="resume" target="../running/history"/>
-                </state>
-            </state>
-
-            <state id="timer" initial="ready">
-                <state id="waiting">
-                    <transition after="self.sccd_yield() + self.timer_duration" target="../ready"/>
-                    <transition event="wake_timer" cond="self.interruptable" target="../ready"/>
-                </state>
-
-                <state id="ready">
-                    <onentry>
-                        <script>
-                            self.unlocked = True
-                        </script>
-                    </onentry>
-                    <transition event="start_timer" target="../waiting">
-                        <parameter name="duration"/>
-                        <parameter name="interruptable"/>
-                        <script>
-                            self.timer_duration = duration
-                            self.interruptable = interruptable
-                        </script>
-                    </transition>
-                </state>
-            </state>
         </parallel>
     </scxml>
 </class>

+ 3 - 3
interface/HUTN/hutn_compiler/primitives_visitor.py

@@ -215,7 +215,7 @@ class PrimitivesVisitor(Visitor):
 
     def visit_lvalue(self, tree):
         symbol = self.get_symbol(tree)
-        if symbol.name in ["__input", "__output"]:
+        if symbol.name in ["input", "output"]:
             return
         r = self.value(Action("resolve"))
         # print symbol.name, symbol.is_func(), symbol.node
@@ -343,7 +343,7 @@ class PrimitivesVisitor(Visitor):
 
     def pre_visit_funcdecl(self, tree):
         symbol = self.get_symbol(tree)
-        if symbol.name in ["__input", "__output"]:
+        if symbol.name in ["input", "output"]:
             return
 
         # TODO: fix funcdecl special case: "X function f(...) = ..."
@@ -374,7 +374,7 @@ class PrimitivesVisitor(Visitor):
 
     def visit_funcdecl(self, tree):
         symbol = self.get_symbol(tree)
-        if symbol.name in ["__input", "__output"]:
+        if symbol.name in ["input", "output"]:
             return
 
         func_body = tree.get_child("func_body")

+ 0 - 1
interface/HUTN/includes/primitives.alh

@@ -92,7 +92,6 @@ Boolean function is_physical_boolean(a : Element)
 Boolean function has_value(a : Element)
 Float function time()
 String function hash(a : String)
-Float function sleep(a : Float)
 
 Element function exec(a : Element)
 Element function resolve(var_name : String)

+ 4 - 0
kernel/modelverse_kernel/main.py

@@ -18,6 +18,7 @@ class ModelverseKernel(object):
     def __init__(self, root):
         self.root = root
         self.returnvalue = None
+        self.success = True
         # request_handlers is a dictionary of tasknames to dictionaries of operations
         # to request handlers. In generics notation:
         #
@@ -91,6 +92,7 @@ class ModelverseKernel(object):
         self.debug_info = defaultdict(list)
 
     def execute_yields(self, taskname, operation, params, reply):
+        self.success = True
         self.taskname = taskname
         if taskname not in self.request_handlers:
             self.request_handlers[taskname] = {}
@@ -106,6 +108,8 @@ class ModelverseKernel(object):
     def execute_rule(self, taskname):
         task_root, =    yield [("RD", [self.root, taskname])]
         if task_root is None:
+            self.success = False
+            self.returnvalue = None
             yield None
         else:
             task_frame, = yield [("RD", [task_root, "frame"])]