about summary refs log tree commit diff stats
path: root/038scheduler.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-09 11:35:47 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-09 11:35:47 -0700
commit45ca3bb7393d264db9817f5e7990cbd7561c058e (patch)
tree02c51ea3e10776985c564a7c89e914336bea498e /038scheduler.cc
parent04ae7fda16d01623d05a68d417b39919211957b3 (diff)
downloadmu-45ca3bb7393d264db9817f5e7990cbd7561c058e.tar.gz
1317 - all tests passing
Hacky new way to turn off child threads.
Diffstat (limited to '038scheduler.cc')
-rw-r--r--038scheduler.cc40
1 files changed, 34 insertions, 6 deletions
diff --git a/038scheduler.cc b/038scheduler.cc
index 99c5484f..4f74bf3e 100644
--- a/038scheduler.cc
+++ b/038scheduler.cc
@@ -53,9 +53,13 @@ void run(recipe_number r) {
     trace("schedule") << current_recipe_name();
 //?     trace("schedule") << Current_routine->id << " " << current_recipe_name(); //? 1
     run_current_routine(Scheduling_interval);
+    // Scheduler State Transitions
     if (Current_routine->completed())
       Current_routine->state = COMPLETED;
     // End Scheduler State Transitions
+
+    // Scheduler Cleanup
+    // End Scheduler Cleanup
   }
 //?   cout << "done with run\n"; //? 1
 }
@@ -64,12 +68,6 @@ void run(recipe_number r) {
 bool all_routines_done() {
   for (index_t i = 0; i < Routines.size(); ++i) {
 //?     cout << "routine " << i << ' ' << Routines.at(i)->state << '\n'; //? 1
-    // Ugly hack: temporarily assume that the first routine spawns helpers.
-    // When the first routine completes we can terminate.
-    // Biggest user of routines right now is tests. When the main test routine
-    // completes the test can terminate.
-    // XXX: We need a better story for when channels close.
-    if (Routines.at(i)->id == 1 && Routines.at(i)->state == COMPLETED) return true;
     if (Routines.at(i)->state == RUNNING) {
       return false;
     }
@@ -110,6 +108,13 @@ Next_routine_id = 1;
 id = Next_routine_id;
 Next_routine_id++;
 
+//: routines save the routine that spawned them
+:(before "End routine Fields")
+// todo: really should be routine_id, but that's less efficient.
+long long int parent_index;  // only < 0 if there's no parent_index
+:(before "End routine Constructor")
+parent_index = -1;
+
 :(before "End Primitive Recipe Declarations")
 START_RUNNING,
 :(before "End Primitive Recipe Numbers")
@@ -119,6 +124,8 @@ case START_RUNNING: {
   assert(isa_literal(current_instruction().ingredients.at(0)));
   assert(!current_instruction().ingredients.at(0).initialized);
   routine* new_routine = new routine(Recipe_number[current_instruction().ingredients.at(0).name]);
+//?   cerr << new_routine->id << " -> " << Current_routine->id << '\n'; //? 1
+  new_routine->parent_index = Current_routine_index;
   // populate ingredients
   for (index_t i = 1; i < current_instruction().ingredients.size(); ++i)
     new_routine->calls.top().ingredient_atoms.push_back(ingredients.at(i));
@@ -211,6 +218,25 @@ recipe f1 [
 +schedule: f1
 -run: idle
 
+//:: Routines are marked completed when their parent completes.
+:(before "End Scheduler Cleanup")
+for (index_t i = 0; i < Routines.size(); ++i) {
+  if (Routines.at(i)->state == COMPLETED) continue;
+  if (Routines.at(i)->parent_index < 0) continue;  // root thread
+  if (has_completed_parent(i)) Routines.at(i)->state = COMPLETED;
+}
+
+:(code)
+bool has_completed_parent(index_t routine_index) {
+//?   cerr << routine_index << '\n'; //? 1
+  for (long long int j = routine_index; j < 0; j = Routines.at(j)->parent_index) {
+//?     cerr << ' ' << j << '\n'; //? 1
+    if (Routines.at(j)->state == COMPLETED)
+      return true;
+  }
+  return false;
+}
+
 //:: 'routine-state' can tell if a given routine id is running
 
 :(scenario routine_state_test)
@@ -248,6 +274,8 @@ case ROUTINE_STATE: {
   break;
 }
 
+//:: miscellaneous helpers
+
 :(before "End Primitive Recipe Declarations")
 RESTART,
 :(before "End Primitive Recipe Numbers")