2015-05-06 16:15:08 +00:00
|
|
|
//: Run a second routine concurrently using 'start-running', without any
|
|
|
|
//: guarantees on how the operations in each are interleaved with each other.
|
2015-04-24 03:42:17 +00:00
|
|
|
|
2015-04-25 07:00:49 +00:00
|
|
|
:(scenario scheduler)
|
2015-04-25 04:39:09 +00:00
|
|
|
recipe f1 [
|
2015-05-01 22:25:47 +00:00
|
|
|
start-running f2:recipe
|
2015-05-10 12:42:56 +00:00
|
|
|
# wait for f2 to run
|
|
|
|
{
|
2015-05-13 17:03:26 +00:00
|
|
|
jump-unless 1:number, -1:literal
|
2015-05-10 12:42:56 +00:00
|
|
|
}
|
2015-04-25 04:39:09 +00:00
|
|
|
]
|
|
|
|
recipe f2 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- copy 1:literal
|
2015-04-25 04:39:09 +00:00
|
|
|
]
|
|
|
|
+schedule: f1
|
|
|
|
+schedule: f2
|
2015-04-24 03:42:17 +00:00
|
|
|
|
2015-04-25 04:39:09 +00:00
|
|
|
//: first, add a deadline to run(routine)
|
|
|
|
//: these changes are ugly and brittle; just close your nose and get through the next few lines
|
2015-04-25 02:58:38 +00:00
|
|
|
:(replace "void run_current_routine()")
|
2015-05-17 09:22:41 +00:00
|
|
|
void run_current_routine(long long int time_slice)
|
|
|
|
:(replace "while (!Current_routine->completed())" following "void run_current_routine(long long int time_slice)")
|
|
|
|
long long int ninstrs = 0;
|
2015-04-27 08:42:07 +00:00
|
|
|
while (Current_routine->state == RUNNING && ninstrs < time_slice)
|
2015-04-24 03:42:17 +00:00
|
|
|
:(after "Running One Instruction")
|
|
|
|
ninstrs++;
|
2015-04-25 04:39:09 +00:00
|
|
|
|
|
|
|
//: now the rest of the scheduler is clean
|
2015-04-27 05:44:47 +00:00
|
|
|
|
|
|
|
:(before "struct routine")
|
|
|
|
enum routine_state {
|
|
|
|
RUNNING,
|
|
|
|
COMPLETED,
|
2015-04-27 08:42:07 +00:00
|
|
|
// End routine States
|
2015-04-27 05:44:47 +00:00
|
|
|
};
|
|
|
|
:(before "End routine Fields")
|
|
|
|
enum routine_state state;
|
|
|
|
:(before "End routine Constructor")
|
|
|
|
state = RUNNING;
|
|
|
|
|
2015-04-25 04:39:09 +00:00
|
|
|
:(before "End Globals")
|
2015-04-27 05:44:47 +00:00
|
|
|
vector<routine*> Routines;
|
2015-05-17 09:22:41 +00:00
|
|
|
long long int Current_routine_index = 0;
|
|
|
|
long long int Scheduling_interval = 500;
|
2015-04-25 07:00:49 +00:00
|
|
|
:(before "End Setup")
|
|
|
|
Scheduling_interval = 500;
|
2015-04-25 04:39:09 +00:00
|
|
|
:(replace{} "void run(recipe_number r)")
|
|
|
|
void run(recipe_number r) {
|
2015-06-01 06:44:52 +00:00
|
|
|
//? cerr << "AAA 4\n"; //? 1
|
2015-04-27 05:44:47 +00:00
|
|
|
Routines.push_back(new routine(r));
|
2015-06-01 06:44:52 +00:00
|
|
|
//? cerr << "AAA " << Routines.size() << " routines\n"; //? 1
|
2015-05-07 22:49:40 +00:00
|
|
|
Current_routine_index = 0, Current_routine = Routines.at(0);
|
2015-04-27 05:44:47 +00:00
|
|
|
while (!all_routines_done()) {
|
2015-05-02 18:49:11 +00:00
|
|
|
skip_to_next_routine();
|
|
|
|
//? cout << "scheduler: " << Current_routine_index << '\n'; //? 1
|
2015-04-27 05:44:47 +00:00
|
|
|
assert(Current_routine);
|
|
|
|
assert(Current_routine->state == RUNNING);
|
2015-05-13 23:33:40 +00:00
|
|
|
trace("schedule") << current_routine_label();
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << Current_routine_index << ": " << current_recipe_name(); //? 1
|
2015-05-08 15:21:36 +00:00
|
|
|
//? trace("schedule") << Current_routine->id << " " << current_recipe_name(); //? 1
|
2015-04-25 04:39:09 +00:00
|
|
|
run_current_routine(Scheduling_interval);
|
2015-05-09 18:35:47 +00:00
|
|
|
// Scheduler State Transitions
|
2015-06-01 06:44:52 +00:00
|
|
|
//? cerr << "AAA completed? " << Current_routine->completed() << '\n'; //? 1
|
2015-04-26 05:30:20 +00:00
|
|
|
if (Current_routine->completed())
|
2015-04-27 05:44:47 +00:00
|
|
|
Current_routine->state = COMPLETED;
|
|
|
|
// End Scheduler State Transitions
|
2015-05-09 18:35:47 +00:00
|
|
|
|
|
|
|
// Scheduler Cleanup
|
|
|
|
// End Scheduler Cleanup
|
2015-04-27 05:44:47 +00:00
|
|
|
}
|
2015-05-02 18:49:11 +00:00
|
|
|
//? cout << "done with run\n"; //? 1
|
2015-04-27 05:44:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
:(code)
|
|
|
|
bool all_routines_done() {
|
2015-05-17 09:22:41 +00:00
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i) {
|
2015-05-07 22:49:40 +00:00
|
|
|
//? cout << "routine " << i << ' ' << Routines.at(i)->state << '\n'; //? 1
|
|
|
|
if (Routines.at(i)->state == RUNNING) {
|
2015-04-27 05:44:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip Current_routine_index past non-RUNNING routines
|
|
|
|
void skip_to_next_routine() {
|
|
|
|
assert(!Routines.empty());
|
2015-05-17 09:22:41 +00:00
|
|
|
assert(Current_routine_index < SIZE(Routines));
|
|
|
|
for (long long int i = (Current_routine_index+1)%SIZE(Routines); i != Current_routine_index; i = (i+1)%SIZE(Routines)) {
|
2015-05-07 22:49:40 +00:00
|
|
|
if (Routines.at(i)->state == RUNNING) {
|
2015-05-02 18:49:11 +00:00
|
|
|
//? cout << "switching to " << i << '\n'; //? 1
|
2015-04-27 05:44:47 +00:00
|
|
|
Current_routine_index = i;
|
2015-05-07 22:49:40 +00:00
|
|
|
Current_routine = Routines.at(i);
|
2015-04-27 05:44:47 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-04-25 04:39:09 +00:00
|
|
|
}
|
2015-05-02 18:49:11 +00:00
|
|
|
//? cout << "all done\n"; //? 1
|
2015-04-25 04:39:09 +00:00
|
|
|
}
|
|
|
|
|
2015-05-13 23:33:40 +00:00
|
|
|
string current_routine_label() {
|
|
|
|
ostringstream result;
|
|
|
|
call_stack calls = Current_routine->calls;
|
|
|
|
for (call_stack::iterator p = calls.begin(); p != calls.end(); ++p) {
|
|
|
|
if (p != calls.begin()) result << '/';
|
|
|
|
result << Recipe[p->running_recipe].name;
|
|
|
|
}
|
|
|
|
return result.str();
|
|
|
|
}
|
|
|
|
|
2015-04-25 04:39:09 +00:00
|
|
|
:(before "End Teardown")
|
2015-05-17 09:22:41 +00:00
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i)
|
2015-05-07 22:49:40 +00:00
|
|
|
delete Routines.at(i);
|
2015-04-27 05:44:47 +00:00
|
|
|
Routines.clear();
|
2015-04-25 04:39:09 +00:00
|
|
|
|
2015-05-06 16:15:08 +00:00
|
|
|
//:: To schedule new routines to run, call 'start-running'.
|
2015-05-06 00:41:10 +00:00
|
|
|
|
2015-05-06 16:15:08 +00:00
|
|
|
//: 'start-running' will return a unique id for the routine that was created.
|
2015-05-13 17:03:26 +00:00
|
|
|
//: routine id is a number, but don't do any arithmetic on it
|
2015-05-06 00:41:10 +00:00
|
|
|
:(before "End routine Fields")
|
2015-05-17 09:22:41 +00:00
|
|
|
long long int id;
|
2015-05-06 00:41:10 +00:00
|
|
|
:(before "End Globals")
|
2015-05-17 09:22:41 +00:00
|
|
|
long long int Next_routine_id = 1;
|
2015-05-06 00:41:10 +00:00
|
|
|
:(before "End Setup")
|
|
|
|
Next_routine_id = 1;
|
|
|
|
:(before "End routine Constructor")
|
|
|
|
id = Next_routine_id;
|
|
|
|
Next_routine_id++;
|
|
|
|
|
2015-05-16 20:17:36 +00:00
|
|
|
//: it needs a new type: 'recipe'
|
|
|
|
:(before "End Mu Types Initialization")
|
|
|
|
Type_number["recipe"] = 0;
|
|
|
|
|
2015-05-09 18:35:47 +00:00
|
|
|
//: 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;
|
|
|
|
|
2015-04-25 04:39:09 +00:00
|
|
|
:(before "End Primitive Recipe Declarations")
|
2015-05-01 22:25:47 +00:00
|
|
|
START_RUNNING,
|
2015-04-25 04:39:09 +00:00
|
|
|
:(before "End Primitive Recipe Numbers")
|
2015-05-01 22:25:47 +00:00
|
|
|
Recipe_number["start-running"] = START_RUNNING;
|
2015-04-25 04:39:09 +00:00
|
|
|
:(before "End Primitive Recipe Implementations")
|
2015-05-01 22:25:47 +00:00
|
|
|
case START_RUNNING: {
|
2015-06-17 19:39:09 +00:00
|
|
|
assert(is_literal(current_instruction().ingredients.at(0)));
|
2015-05-07 22:06:53 +00:00
|
|
|
assert(!current_instruction().ingredients.at(0).initialized);
|
|
|
|
routine* new_routine = new routine(Recipe_number[current_instruction().ingredients.at(0).name]);
|
2015-05-09 18:35:47 +00:00
|
|
|
//? cerr << new_routine->id << " -> " << Current_routine->id << '\n'; //? 1
|
|
|
|
new_routine->parent_index = Current_routine_index;
|
2015-05-06 02:39:20 +00:00
|
|
|
// populate ingredients
|
2015-05-17 09:22:41 +00:00
|
|
|
for (long long int i = 1; i < SIZE(current_instruction().ingredients); ++i)
|
2015-05-13 23:33:40 +00:00
|
|
|
new_routine->calls.front().ingredient_atoms.push_back(ingredients.at(i));
|
2015-05-06 00:41:10 +00:00
|
|
|
Routines.push_back(new_routine);
|
2015-05-07 22:06:53 +00:00
|
|
|
products.resize(1);
|
2015-05-13 00:00:56 +00:00
|
|
|
products.at(0).push_back(new_routine->id);
|
2015-04-25 04:39:09 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-04-25 07:00:49 +00:00
|
|
|
|
2015-05-02 18:49:11 +00:00
|
|
|
:(scenario scheduler_runs_single_routine)
|
|
|
|
% Scheduling_interval = 1;
|
|
|
|
recipe f1 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- copy 0:literal
|
|
|
|
2:number <- copy 0:literal
|
2015-05-02 18:49:11 +00:00
|
|
|
]
|
|
|
|
+schedule: f1
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: 1:number <- copy 0:literal
|
2015-05-02 18:49:11 +00:00
|
|
|
+schedule: f1
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: 2:number <- copy 0:literal
|
2015-05-02 18:49:11 +00:00
|
|
|
|
2015-04-25 07:00:49 +00:00
|
|
|
:(scenario scheduler_interleaves_routines)
|
|
|
|
% Scheduling_interval = 1;
|
|
|
|
recipe f1 [
|
2015-05-01 22:25:47 +00:00
|
|
|
start-running f2:recipe
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- copy 0:literal
|
|
|
|
2:number <- copy 0:literal
|
2015-04-25 07:00:49 +00:00
|
|
|
]
|
|
|
|
recipe f2 [
|
2015-05-21 19:36:59 +00:00
|
|
|
3:number <- copy 0:literal
|
|
|
|
4:number <- copy 0:literal
|
2015-04-25 07:00:49 +00:00
|
|
|
]
|
|
|
|
+schedule: f1
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: start-running f2:recipe
|
2015-04-25 07:00:49 +00:00
|
|
|
+schedule: f2
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: 3:number <- copy 0:literal
|
2015-04-25 07:00:49 +00:00
|
|
|
+schedule: f1
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: 1:number <- copy 0:literal
|
2015-04-25 07:00:49 +00:00
|
|
|
+schedule: f2
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: 4:number <- copy 0:literal
|
2015-04-25 07:00:49 +00:00
|
|
|
+schedule: f1
|
2015-05-21 19:36:59 +00:00
|
|
|
+run: 2:number <- copy 0:literal
|
2015-05-02 18:49:11 +00:00
|
|
|
|
2015-05-06 02:39:20 +00:00
|
|
|
:(scenario start_running_takes_args)
|
|
|
|
recipe f1 [
|
|
|
|
start-running f2:recipe, 3:literal
|
2015-05-10 12:42:56 +00:00
|
|
|
# wait for f2 to run
|
|
|
|
{
|
2015-05-13 17:03:26 +00:00
|
|
|
jump-unless 1:number, -1:literal
|
2015-05-10 12:42:56 +00:00
|
|
|
}
|
2015-05-06 02:39:20 +00:00
|
|
|
]
|
|
|
|
recipe f2 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- next-ingredient
|
|
|
|
2:number <- add 1:number, 1:literal
|
2015-05-06 02:39:20 +00:00
|
|
|
]
|
|
|
|
+mem: storing 4 in location 2
|
|
|
|
|
2015-05-06 00:41:10 +00:00
|
|
|
:(scenario start_running_returns_routine_id)
|
|
|
|
recipe f1 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- start-running f2:recipe
|
2015-05-06 00:41:10 +00:00
|
|
|
]
|
|
|
|
recipe f2 [
|
2015-05-13 17:03:26 +00:00
|
|
|
12:number <- copy 44:literal
|
2015-05-06 00:41:10 +00:00
|
|
|
]
|
|
|
|
+mem: storing 2 in location 1
|
|
|
|
|
2015-05-27 18:27:50 +00:00
|
|
|
//: this scenario will require some careful setup in escaped C++
|
|
|
|
//: (straining our tangle capabilities to near-breaking point)
|
2015-05-02 18:49:11 +00:00
|
|
|
:(scenario scheduler_skips_completed_routines)
|
2015-05-13 17:03:26 +00:00
|
|
|
% recipe_number f1 = load("recipe f1 [\n1:number <- copy 0:literal\n]").front();
|
|
|
|
% recipe_number f2 = load("recipe f2 [\n2:number <- copy 0:literal\n]").front();
|
2015-05-02 18:49:11 +00:00
|
|
|
% Routines.push_back(new routine(f1)); // f1 meant to run
|
|
|
|
% Routines.push_back(new routine(f2));
|
|
|
|
% Routines.back()->state = COMPLETED; // f2 not meant to run
|
|
|
|
#? % Trace_stream->dump_layer = "all";
|
|
|
|
# must have at least one routine without escaping
|
|
|
|
recipe f3 [
|
2015-05-13 17:03:26 +00:00
|
|
|
3:number <- copy 0:literal
|
2015-05-02 18:49:11 +00:00
|
|
|
]
|
|
|
|
# by interleaving '+' lines with '-' lines, we allow f1 and f3 to run in any order
|
|
|
|
+schedule: f1
|
|
|
|
+mem: storing 0 in location 1
|
|
|
|
-schedule: f2
|
|
|
|
-mem: storing 0 in location 2
|
|
|
|
+schedule: f3
|
|
|
|
+mem: storing 0 in location 3
|
|
|
|
|
|
|
|
:(scenario scheduler_starts_at_middle_of_routines)
|
|
|
|
% Routines.push_back(new routine(COPY));
|
|
|
|
% Routines.back()->state = COMPLETED;
|
|
|
|
recipe f1 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- copy 0:literal
|
|
|
|
2:number <- copy 0:literal
|
2015-05-02 18:49:11 +00:00
|
|
|
]
|
|
|
|
+schedule: f1
|
|
|
|
-run: idle
|
2015-05-06 00:54:46 +00:00
|
|
|
|
2015-05-09 18:35:47 +00:00
|
|
|
//:: Routines are marked completed when their parent completes.
|
2015-05-10 12:42:56 +00:00
|
|
|
|
|
|
|
:(scenario scheduler_kills_orphans)
|
|
|
|
recipe main [
|
|
|
|
start-running f1:recipe
|
|
|
|
# f1 never actually runs because its parent completes without waiting for it
|
|
|
|
]
|
|
|
|
recipe f1 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number <- copy 0:literal
|
2015-05-10 12:42:56 +00:00
|
|
|
]
|
|
|
|
-schedule: f1
|
|
|
|
|
2015-05-09 18:35:47 +00:00
|
|
|
:(before "End Scheduler Cleanup")
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << "Before cleanup"; //? 1
|
2015-05-17 09:22:41 +00:00
|
|
|
//? for (long long int i = 0; i < SIZE(Routines); ++i) { //? 1
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << i << ": " << Routines.at(i)->id << ' ' << Routines.at(i)->state << ' ' << Routines.at(i)->parent_index << ' ' << Routines.at(i)->state; //? 1
|
|
|
|
//? } //? 1
|
2015-05-17 09:22:41 +00:00
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i) {
|
2015-05-09 18:35:47 +00:00
|
|
|
if (Routines.at(i)->state == COMPLETED) continue;
|
|
|
|
if (Routines.at(i)->parent_index < 0) continue; // root thread
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << "AAA " << i; //? 1
|
|
|
|
if (has_completed_parent(i)) {
|
|
|
|
//? trace("schedule") << "BBB " << i; //? 1
|
|
|
|
Routines.at(i)->state = COMPLETED;
|
|
|
|
}
|
2015-05-09 18:35:47 +00:00
|
|
|
}
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << "After cleanup"; //? 1
|
2015-05-17 09:22:41 +00:00
|
|
|
//? for (long long int i = 0; i < SIZE(Routines); ++i) { //? 1
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << i << ": " << Routines.at(i)->id << ' ' << Routines.at(i)->state << ' ' << Routines.at(i)->parent_index << ' ' << Routines.at(i)->state; //? 1
|
|
|
|
//? } //? 1
|
2015-05-09 18:35:47 +00:00
|
|
|
|
|
|
|
:(code)
|
2015-05-17 09:22:41 +00:00
|
|
|
bool has_completed_parent(long long int routine_index) {
|
2015-05-10 12:42:56 +00:00
|
|
|
//? trace("schedule") << "CCC " << routine_index << '\n'; //? 2
|
|
|
|
for (long long int j = routine_index; j >= 0; j = Routines.at(j)->parent_index) {
|
|
|
|
//? trace("schedule") << "DDD " << j << '\n'; //? 2
|
2015-05-09 18:35:47 +00:00
|
|
|
if (Routines.at(j)->state == COMPLETED)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-05-06 00:54:46 +00:00
|
|
|
//:: 'routine-state' can tell if a given routine id is running
|
|
|
|
|
|
|
|
:(scenario routine_state_test)
|
|
|
|
% Scheduling_interval = 2;
|
|
|
|
recipe f1 [
|
2015-05-13 17:03:26 +00:00
|
|
|
1:number/child-id <- start-running f2:recipe
|
|
|
|
12:number <- copy 0:literal # race condition since we don't care about location 12
|
2015-05-06 00:54:46 +00:00
|
|
|
# thanks to Scheduling_interval, f2's one instruction runs in between here and completes
|
2015-05-13 17:03:26 +00:00
|
|
|
2:number/state <- routine-state 1:number/child-id
|
2015-05-06 00:54:46 +00:00
|
|
|
]
|
|
|
|
recipe f2 [
|
2015-05-13 17:03:26 +00:00
|
|
|
12:number <- copy 0:literal
|
2015-05-06 00:54:46 +00:00
|
|
|
# trying to run a second instruction marks routine as completed
|
|
|
|
]
|
|
|
|
# recipe f2 should be in state COMPLETED
|
|
|
|
+mem: storing 1 in location 2
|
|
|
|
|
|
|
|
:(before "End Primitive Recipe Declarations")
|
|
|
|
ROUTINE_STATE,
|
|
|
|
:(before "End Primitive Recipe Numbers")
|
|
|
|
Recipe_number["routine-state"] = ROUTINE_STATE;
|
|
|
|
:(before "End Primitive Recipe Implementations")
|
|
|
|
case ROUTINE_STATE: {
|
2015-05-17 09:22:41 +00:00
|
|
|
assert(scalar(ingredients.at(0)));
|
|
|
|
long long int id = ingredients.at(0).at(0);
|
2015-05-07 22:06:53 +00:00
|
|
|
long long int result = -1;
|
2015-05-17 09:22:41 +00:00
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i) {
|
2015-05-07 22:49:40 +00:00
|
|
|
if (Routines.at(i)->id == id) {
|
|
|
|
result = Routines.at(i)->state;
|
2015-05-06 00:54:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-05-07 22:06:53 +00:00
|
|
|
products.resize(1);
|
2015-05-13 00:00:56 +00:00
|
|
|
products.at(0).push_back(result);
|
2015-05-06 00:54:46 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-05-08 01:35:33 +00:00
|
|
|
|
2015-05-09 18:35:47 +00:00
|
|
|
//:: miscellaneous helpers
|
|
|
|
|
2015-05-08 01:35:33 +00:00
|
|
|
:(before "End Primitive Recipe Declarations")
|
|
|
|
RESTART,
|
|
|
|
:(before "End Primitive Recipe Numbers")
|
|
|
|
Recipe_number["restart"] = RESTART;
|
|
|
|
:(before "End Primitive Recipe Implementations")
|
|
|
|
case RESTART: {
|
2015-05-17 09:22:41 +00:00
|
|
|
assert(scalar(ingredients.at(0)));
|
|
|
|
long long int id = ingredients.at(0).at(0);
|
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i) {
|
2015-05-08 01:35:33 +00:00
|
|
|
if (Routines.at(i)->id == id) {
|
|
|
|
Routines.at(i)->state = RUNNING;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2015-05-08 15:21:36 +00:00
|
|
|
|
2015-05-10 13:02:36 +00:00
|
|
|
:(before "End Primitive Recipe Declarations")
|
|
|
|
STOP,
|
|
|
|
:(before "End Primitive Recipe Numbers")
|
|
|
|
Recipe_number["stop"] = STOP;
|
|
|
|
:(before "End Primitive Recipe Implementations")
|
|
|
|
case STOP: {
|
2015-05-17 09:22:41 +00:00
|
|
|
assert(scalar(ingredients.at(0)));
|
|
|
|
long long int id = ingredients.at(0).at(0);
|
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i) {
|
2015-05-10 13:02:36 +00:00
|
|
|
if (Routines.at(i)->id == id) {
|
|
|
|
Routines.at(i)->state = COMPLETED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:21:36 +00:00
|
|
|
:(before "End Primitive Recipe Declarations")
|
|
|
|
_DUMP_ROUTINES,
|
|
|
|
:(before "End Primitive Recipe Numbers")
|
|
|
|
Recipe_number["$dump-routines"] = _DUMP_ROUTINES;
|
|
|
|
:(before "End Primitive Recipe Implementations")
|
|
|
|
case _DUMP_ROUTINES: {
|
2015-05-17 09:22:41 +00:00
|
|
|
for (long long int i = 0; i < SIZE(Routines); ++i) {
|
2015-05-10 12:42:56 +00:00
|
|
|
cerr << i << ": " << Routines.at(i)->id << ' ' << Routines.at(i)->state << ' ' << Routines.at(i)->parent_index << '\n';
|
2015-05-08 15:21:36 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|