about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-08-16 20:12:14 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-08-16 20:12:14 -0700
commit88e9989473226492f76cf5dc6b22eeb36fd97e49 (patch)
treee00ee460e3f5d302b12bf877cd0f08750ed50384
parent5db2faebe215e588172bcfe1810416f4c7b909b1 (diff)
downloadmu-88e9989473226492f76cf5dc6b22eeb36fd97e49.tar.gz
2023 - give routines time limits
-rw-r--r--038scheduler.cc63
1 files changed, 63 insertions, 0 deletions
diff --git a/038scheduler.cc b/038scheduler.cc
index 613491b5..dc4d56f1 100644
--- a/038scheduler.cc
+++ b/038scheduler.cc
@@ -375,3 +375,66 @@ case _DUMP_ROUTINES: {
   }
   break;
 }
+
+//: support for stopping routines after some number of cycles
+
+:(scenario routine_discontinues_past_limit)
+% Scheduling_interval = 2;
+recipe f1 [
+  1:number/child-id <- start-running f2:recipe
+  limit-time 1:number/child-id, 1
+]
+recipe f2 [
+{
+  loop  # run forever
+}
+]
+# f2 terminates
++schedule: discontinuing routine 2
+
+:(before "End routine States")
+DISCONTINUED,
+:(before "End Scheduler State Transitions")
+if (Current_routine->limit >= 0) {
+  if (Current_routine->limit <= Scheduling_interval) {
+    trace("schedule") << "discontinuing routine " << Current_routine->id << end();
+    Current_routine->state = DISCONTINUED;
+    Current_routine->limit = 0;
+  }
+  else {
+    Current_routine->limit -= Scheduling_interval;
+  }
+}
+
+:(before "End routine Fields")
+long long int limit;
+:(before "End routine Constructor")
+limit = -1;  /* no limit */
+
+:(before "End Primitive Recipe Declarations")
+LIMIT_TIME,
+:(before "End Primitive Recipe Numbers")
+Recipe_ordinal["limit-time"] = LIMIT_TIME;
+:(before "End Primitive Recipe Implementations")
+case LIMIT_TIME: {
+  if (SIZE(ingredients) != 2) {
+    raise << current_recipe_name() << ": 'limit-time' requires exactly two ingredient, but got " << current_instruction().to_string() << '\n' << end();
+    break;
+  }
+  if (!scalar(ingredients.at(0))) {
+    raise << current_recipe_name() << ": first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
+    break;
+  }
+  if (!scalar(ingredients.at(1))) {
+    raise << current_recipe_name() << ": second ingredient of 'limit-time' should be a number (of instructions to run for), but got " << current_instruction().ingredients.at(1).original_string << '\n' << end();
+    break;
+  }
+  long long int id = ingredients.at(0).at(0);
+  for (long long int i = 0; i < SIZE(Routines); ++i) {
+    if (Routines.at(i)->id == id) {
+      Routines.at(i)->limit = ingredients.at(1).at(0);
+      break;
+    }
+  }
+  break;
+}