// src/backend/text_simulation.cc - Copyright 2005, 2006, University // of Padova, dept. of Pure and Applied // Mathematics // // This file is part of SGPEMv2. // // This is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // SGPEMv2 is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with SGPEMv2; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "backend/string_utils.hh" #include "text_simulation.hh" using namespace std; using namespace sgpem; using namespace memory; using Glib::Thread; using Glib::ustring; TextSimulation::~TextSimulation() { } /**Adds an IO_device and creates a thread which loops the read-parse-execute process */ void TextSimulation::add_io_device(smart_ptr io) { _devices.push_back(io); pair p(this, 0); Thread::create( sigc::bind(&TextSimulation::_io_loop, p), true); } void TextSimulation::parse_command(pair< pair, const ustring > p) { TextSimulation* obj = p.first.first; int quale = p.first.second; ustring str = p.second; if (str.length() == 0) return; //CAPITALIZE alla grguments str = str.uppercase(); vector arguments; uint f=0; static const ustring whitespaces = " \r\b\n\t\a"; //fills the vector with parameters while (true) { f = str.find_first_of(whitespaces); if (f > str.length()) { //the end of the string arguments.push_back(str); break; } else { //add the token arguments.push_back(str.substr(0, f)); //trim the initial whitespaces str = str.substr(f+1); f = str.find_first_not_of(whitespaces); str = str.substr(f); } } if (arguments.size() == 0) return; bool show_help = false; int param = 0; check: if (arguments[param] == "RUN") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- RUN COMMAND --\nStarts the simulation. It can be continuous or step-by-step" " depending the mode configured with SetMode (default=continuous)")); return; } obj->run(); } else if (arguments[param] == "PAUSE") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- PAUSE COMMAND --\nPauses the simulation. The next call to RUN will restart it.")); return; } obj->pause(); } else if (arguments[param] == "STOP") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- STOP COMMAND --\nStops the simulation. The next call to RUN will " "bring the simulation to the FIRST instant and start it.")); return; } obj->stop(); } else if (arguments[param] == "RESET") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- RESET COMMAND --\nResets the simulation jumping back to the first instant.")); return; } obj->reset(); } else if (arguments[param] == "QUIT") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- QUIT COMMAND --\nExits the program.")); return; } obj->_devices[quale]->write_buffer(_("\n\n*** Thank you for using SGPEM by Sirius Cybernetics Corporation ***\n\n")); exit(1); } else if (arguments[param] == "HELP") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- Do you really want me to explain what HELP means? --" "\n ************** YOU ARE JOKING ME !!! ************\n\n")); exit(1); } if (arguments.size() == 1) { obj->_devices[quale]->write_buffer( "\nAvaiable commands:\nRUN\nPAUSE\nSTOP\nRESET\nQUIT\nHELP" "\nGETMODE\nSETMODE\nSETTIMER\nGETTIMER\nJUMPTO\nGETPOLICY" "\nSETPOLICY\nGETPOLICYATTRIBUTES" "\n\nHELP followed by a command shows help about it." "\n ex. HELP RUN shows help about the command RUN"); return; } show_help = true; param = 1; goto check; } else if (arguments[param] == "SETMODE") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- SetMode COMMAND --\nPermits to change the mode of the simulation.\n\nSintax: Setmode \n\t can take values:\n" "\n\t\tCONTINUOUS - when calling RUN the simulation will show an animation using the wait-interval set by SETTIMER\n" "\n\t\tSTEP - when calling RUN the simulation will show only one step of the animation\n")); return; } if (arguments.size() != 2) { obj->_devices[quale]->write_buffer(_("\nERROR: wrong number of parameters." "\nType HELP SETMODE for the description of the sintax")); return; } if (arguments[1] == "CONTINUOUS") obj->set_mode(true); else if (arguments[1] == "STEP") obj->set_mode(false); else obj->_devices[quale]->write_buffer(_("\nERROR: the second parameter can be only CONTINUOUS or STEP")); } else if (arguments[param] == "GETMODE") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- GetMode COMMAND --\nReturns\n\tCONTINUOUS : if the simulation is shown with an animation" "\n\tSTEP : if if the simulation is shown step-by-step")); return; } if (obj->get_mode()) obj->_devices[quale]->write_buffer(_("\nCONTINUOUS")); else obj->_devices[quale]->write_buffer(_("\nSTEP")); } else if (arguments[param] == "SETTIMER") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- SetTimer COMMAND --\nPermits to change the interval between a step and the following one during a continuous animation." "\n\nSintax: SetTimer \n\t must be an integer value > 0 and < 10000.\n")); return; } if (arguments.size() != 2) { obj->_devices[quale]->write_buffer(_("\nERROR: wrong number of parameters." "\nType HELP SETTIMER for the description of the sintax")); return; } int num; if (string_to_int(arguments[1], num) && num > 0 && num < 10000) obj->set_timer(num); else obj->_devices[quale]->write_buffer(_( "\nERROR: the second parameter has a wrong value." "\nType HELP SETTIMER for the description of the sintax")); } else if (arguments[param] == "GETTIMER") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- GetTimer COMMAND --\nReturns the number of milliseconds the simulation " "in the continuous mode waits between a step and the following one")); return; } ustring ss; int_to_string(obj->get_timer(), ss); obj->_devices[quale]->write_buffer(ss); } else if (arguments[param] == "JUMPTO") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- JumpTo COMMAND --\nPermits to jump to a desired instant of the simulation." " All states of the simulation before will be recalculated and printed out." "\n\nSintax: JumpTo \n\t must be an integer value >= 0")); return; } if (arguments.size() != 2) { obj->_devices[quale]->write_buffer(_("\nERROR: wrong number of parameters." "\nType HELP JUMPTO for the description of the sintax")); return; } int num; if (string_to_int(arguments[1], num) && num >= 0) obj->jump_to(num); else obj->_devices[quale]->write_buffer(_( "\nERROR: the second parameter has a wrong value." "\nType HELP JUMPTO for the description of the sintax")); } else if (arguments[param] == "GETPOLICY") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- GetPolicy COMMAND --\nReturns the name and the description of the current applied policy.")); return; } obj->_devices[quale]->write_buffer(obj->get_policy()->get_description()); } else if (arguments[param] == "GETPOLICYATTRIBUTES") { if (show_help) { obj->_devices[quale]->write_buffer(_( "\n-- GetPolicyAttributes COMMAND --\nReturns the list of attributes of the current applied policy." "\nThe description of each parameter includes:" "\n\tthe NAME of the marameter with its type\n\tits current VALUE" "\n\tits LOWER and UPPER bounds\n\twhether the parameter is REQUIRED")); return; } ustring temp; const PolicyParameters& param = obj->get_policy()->get_parameters(); map > map_i = param.get_registered_int_parameters(); map >::iterator i_i = map_i.begin(); for(; i_i != map_i.end(); i_i++) { obj->_devices[quale]->write_buffer("\nint\t" + i_i->second.get_name()); int_to_string(i_i->second.get_value(), temp); obj->_devices[quale]->write_buffer("\tvalue=" + temp); int_to_string(i_i->second.get_lower_bound(), temp); obj->_devices[quale]->write_buffer("\t\tlower=" + temp); int_to_string(i_i->second.get_upper_bound(), temp); obj->_devices[quale]->write_buffer("\t\tupper=" + temp); if (i_i->second.is_required()) obj->_devices[quale]->write_buffer("\t\trequired=true"); else obj->_devices[quale]->write_buffer("\t\trequired=false"); } map > map_f = param.get_registered_float_parameters(); map >::iterator i_f = map_f.begin(); for(; i_f != map_f.end(); i_f++) { obj->_devices[quale]->write_buffer("\nfloat\t" + i_f->second.get_name()); float_to_string(i_f->second.get_value(), temp); obj->_devices[quale]->write_buffer("\tvalue=" + temp); float_to_string(i_f->second.get_lower_bound(), temp); obj->_devices[quale]->write_buffer("\t\tlower=" + temp); float_to_string(i_f->second.get_upper_bound(), temp); obj->_devices[quale]->write_buffer("\t\tupper=" + temp); if (i_f->second.is_required()) obj->_devices[quale]->write_buffer("\t\trequired=true"); else obj->_devices[quale]->write_buffer("\t\trequired=false"); } map > map_s = param.get_registered_string_parameters(); map >::iterator i_s = map_s.begin(); for(; i_s != map_s.end(); i_s++) { obj->_devices[quale]->write_buffer("\nustring\t" + i_s->second.get_name()); obj->_devices[quale]->write_buffer("\tvalue=" + i_s->second.get_value()); if (i_s->second.is_required()) obj->_devices[quale]->write_buffer(" required=true"); else obj->_devices[quale]->write_buffer(" required=false"); } } else { obj->_devices[quale]->write_buffer(_("\nCommand not recognized: ")); obj->_devices[quale]->write_buffer(arguments[param]); obj->_devices[quale]->write_buffer(_("\nTyper HELP for a list of avaiable commands.")); return; } } void TextSimulation::update() { History& h = History::get_instance(); int when, pri; ustring temp; when = h.get_current_time(); smart_ptr ll = h.get_simulation_status_at(when); int_to_string(when, temp); if (when<10) _devices[0]->write_buffer("\n "); else _devices[0]->write_buffer("\n"); _devices[0]->write_buffer(temp + ") [RUNS]"); //insert the RUNNING ONE smart_ptr running = h.get_scheduled_at(when); if (running) { pri = running->get_schedulable()->get_priority(); int_to_string(pri, temp); _devices[0]->write_buffer(" " + running->get_schedulable()->get_name() + "_(" + temp + ")"); } _devices[0]->write_buffer(" --[READY]"); //insert the READY ones for (uint i = 0; i < ll->size(); i++) if (ll->get_item_at(i)->get_state() == SchedulableStatus::state_ready) { pri = ll->get_item_at(i)->get_schedulable()->get_priority(); int_to_string(pri, temp); _devices[0]->write_buffer(" " + ll->get_item_at(i)->get_schedulable()->get_name() + "_(" + temp + ")"); } _devices[0]->write_buffer(" --[BLOCKED]"); //insert the BLOCKED ones for (uint i = 0; i < ll->size(); i++) if (ll->get_item_at(i)->get_state() == SchedulableStatus::state_blocked) { pri = ll->get_item_at(i)->get_schedulable()->get_priority(); int_to_string(pri, temp); _devices[0]->write_buffer(" " + ll->get_item_at(i)->get_schedulable()->get_name() + "_(" + temp + ")"); } _devices[0]->write_buffer(" --[FUTURE]"); //insert the FUTURE ones for (uint i = 0; i < ll->size(); i++) if (ll->get_item_at(i)->get_state() == SchedulableStatus::state_future) { pri = ll->get_item_at(i)->get_schedulable()->get_priority(); int_to_string(pri, temp); _devices[0]->write_buffer(" " + ll->get_item_at(i)->get_schedulable()->get_name() + "_(" + temp + ")"); } _devices[0]->write_buffer(" --[TERM]"); //insert the TERMINATED ones for (uint i = 0; i < ll->size(); i++) if (ll->get_item_at(i)->get_state() == SchedulableStatus::state_terminated) { pri = ll->get_item_at(i)->get_schedulable()->get_priority(); int_to_string(pri, temp); _devices[0]->write_buffer(" " + ll->get_item_at(i)->get_schedulable()->get_name() + "_(" + temp + ")"); } } void TextSimulation::_io_loop(pair pun) { while(true) { //reads the command ustring str; pun.first->_devices[pun.second]->write_buffer("\nSGPEM=> "); str = pun.first->_devices[pun.second]->read_command(); pair, const ustring> p(pair(pun.first, pun.second), str); if (pun.first->_devices[pun.second]->is_full_duplex()) //if the IOManager can read AND write at the same time then create a new thread //thath will write to it while going on reading the next command Thread::create( sigc::bind(&TextSimulation::parse_command, p), true); else //no read is possible: only write pun.first->parse_command(p); } }