// src/simulation_controller.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 3 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, see http://www.gnu.org/licenses/. #include "gettext.h" #include "simulation_controller.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef NDEBUG #include #endif using namespace sgpem; using Gnome::Glade::Xml; SimulationController::SimulationController(Simulation& simulation, Glib::RefPtr refXml) : _sim(simulation), _break_requested(false) { using namespace Gtk; _sim.attach(*this); // Start, pause and stop simulation from the toolbar // TODO: can we use action groups instead of this? refXml->get_widget("ToolBar.Play", _toolbt_start); refXml->get_widget("ToolBar.Pause", _toolbt_pause); refXml->get_widget("ToolBar.Stop", _toolbt_stop); refXml->get_widget("MenuItem.Simulation.Play", _menuit_start); refXml->get_widget("MenuItem.Simulation.Pause", _menuit_pause); refXml->get_widget("MenuItem.Simulation.Stop", _menuit_stop); _toolbt_start->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_run)); _toolbt_pause->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_pause)); _toolbt_stop->signal_clicked().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_stop)); _menuit_start->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_run)); _menuit_pause->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_pause)); _menuit_stop->signal_activate().connect(sigc::mem_fun(*this, &SimulationController::on_simulation_stop)); } SimulationController::~SimulationController() { _sim.detach(*this); } void SimulationController::on_simulation_run() { // Sensitivities _toolbt_start->set_sensitive(false); _toolbt_pause->set_sensitive(true); _toolbt_stop->set_sensitive(true); _menuit_start->set_sensitive(false); _menuit_pause->set_sensitive(true); _menuit_stop->set_sensitive(true); _break_requested = false; // Used instead of simply calling "_sim.run()" to // have exception handling only in one place: run_simulation_adaptor(); } void SimulationController::on_simulation_pause() { // Sensitivities _toolbt_start->set_sensitive(true); _toolbt_pause->set_sensitive(false); _toolbt_stop->set_sensitive(true); _menuit_start->set_sensitive(true); _menuit_pause->set_sensitive(false); _menuit_stop->set_sensitive(true); _break_requested = true; _sim.pause(); } void SimulationController::on_simulation_stop() { // Sensitivities _toolbt_start->set_sensitive(true); _toolbt_pause->set_sensitive(false); _toolbt_stop->set_sensitive(false); _menuit_start->set_sensitive(true); _menuit_pause->set_sensitive(false); _menuit_stop->set_sensitive(false); _break_requested = true; _sim.stop(); } void SimulationController::update(const Simulation& simulation) { #ifndef NDEBUG std::cerr << "SimulationController::update(), simulation state == " << std::hex << simulation.get_state() << std::endl; #endif if(_break_requested) return; switch(simulation.get_state()) { case Simulation::state_stopped: on_simulation_stop(); return; case Simulation::state_paused: on_simulation_pause(); return; case Simulation::state_running: // Go on with the rest of the method... break; } // We should never enter here, if the code is correct: // a step by step simulation should always be in paused // or stopped state after performing a single step assert(simulation.get_mode() != Simulation::mode_step_by_step); switch(simulation.get_mode()) { case Simulation::mode_continuous: { int timeout = GlobalPreferences::get_instance().get_speed(); Glib::signal_timeout().connect(sigc::mem_fun(*this, &SimulationController::run_simulation_adaptor), timeout); } break; default: // Never gets here. break; } } bool SimulationController::run_simulation_adaptor() { using Gtk::MessageDialog; using namespace Glib; if(!_break_requested) try { _sim.run(); } catch(const UserInterruptException& uie) { // Show the user a dialog MessageDialog diag(_("The selected user CPU policy stopped before returning:\n") + Markup::escape_text(uie.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); diag.run(); } catch(const MalformedPolicyException& mpe) { // Show user a dialog MessageDialog diag(_("The selected user CPU policy was malformed and failed to sort the queue:\n") + Markup::escape_text(mpe.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); diag.run(); try { // Deactivate the policy _sim.set_policy(NULL); } catch(const CPUPolicyException& cpe) { // Fatal error. We should never get here. std::cerr << _(" [EE] Fatal error. Impossible to deactivate the policy in ") << __FILE__ << ":" << __LINE__ << std::endl << _(" [EE] ") << cpe.what() << std::endl; ; abort(); } } catch(const NullPolicyException& npe) { MessageDialog diag(_("No active policy selected:\n") + Markup::escape_text(npe.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); diag.run(); } catch(const CPUPolicyException& cpe) { MessageDialog diag(_("Unexpected error:\n") + Markup::escape_text(cpe.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); diag.run(); } return false; }