// src/backend/concrete_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 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 "concrete_simulation.hh" #include #include #include #include #include #include #include #include #include #include using namespace sgpem; ConcreteSimulation::ConcreteSimulation () : Simulation (), _state (state_stopped), _mode (mode_continuous), _policy (NULL), _resource_policy (NULL) { } void ConcreteSimulation::set_mode (const mode new_mode) { _mode = new_mode; } Simulation::mode ConcreteSimulation::get_mode () const { return _mode; } void ConcreteSimulation::jump_to (History::position p) { switch (_state) { case state_running: // pauses the simulation (done below) break; case state_stopped: _history.set_front (0); break; default: break; } // Disable momentarily updates for registered observers on // sgpem::Simulation and sgpem::History. History::LockNotify h_lock (_history); Simulation::LockNotify s_lock (*this); pause (); bool yet_to_finish = true; History::position increment = 0; while (yet_to_finish && p > _history.get_front () + increment) { yet_to_finish = step (); increment++; } get_history ().set_front (std::min (p, _history.get_size ())); if (!yet_to_finish) stop (); } void ConcreteSimulation::pause () { if (_state != state_paused) { _state = state_paused; notify_change (); } } void ConcreteSimulation::stop () { if (_state != state_stopped) { _state = state_stopped; notify_change (); } } void ConcreteSimulation::run () { switch (_state) { case state_stopped: _history.set_front (0); break; default: break; } _state = state_running; //step forward bool yet_to_finish = step (); _history.set_front (_history.get_front () + 1); if (yet_to_finish) { if (_mode == mode_step_by_step) pause (); else // We remain in running state, and we notify everybody! // This is non-trivial, and we must do so since we // put the state to running inconditionally. Don't // touch this if you don't provide another way to tell // a SimulationObserver that the simulation advanced // and *yet* it is in running state! notify_change (); } else // Simulation ended stop (); } bool ConcreteSimulation::step () { if (get_policy () == nullptr) { stop (); throw NullPolicyException ("no CPU policy selected"); } if (get_resource_policy () == nullptr) { stop (); throw NullPolicyException ("no resource policy selected"); } try { // step forward bool yet_to_finish = true; if (_history.get_front () == _history.get_size () - 1) { if (!_history.is_sealed ()) yet_to_finish = Scheduler::get_instance ().step_forward (_history, *get_policy (), *get_resource_policy ()); else yet_to_finish = false; } if (!yet_to_finish) _history.seal (); // since the simulation expects to be notified // of simulation termination when reaching the last environment // and the front will be updated just out of this method, // we have to make this horrible thing if (_history.get_front () == _history.get_size () - 2 && _history.is_sealed ()) yet_to_finish = false; return yet_to_finish; } catch (const CPUPolicyException &e) { stop (); throw; } } Simulation::state ConcreteSimulation::get_state () const { return _state; } ConcreteHistory & ConcreteSimulation::get_history () { return _history; } const ConcreteHistory & ConcreteSimulation::get_history () const { return _history; } void ConcreteSimulation::set_policy (CPUPolicy *p) { stop (); try { CPUPoliciesGatekeeper::get_instance ().activate_policy (&_history, p); _policy = p; } catch (const CPUPolicyException &e1) { try { // this is a no-op if _policy is nullptr CPUPoliciesGatekeeper::get_instance ().activate_policy (&_history, _policy); } catch (const CPUPolicyException &e2) { _policy = nullptr; std::string msg = _ ("unable to change policy and to restore the previous: "); msg += e2.what (); throw CPUPolicyException (msg); } std::string msg = _ ("unable to change policy: "); msg += e1.what (); throw CPUPolicyException (msg); } } CPUPolicy * ConcreteSimulation::get_policy () { return _policy; } void ConcreteSimulation::set_resource_policy (ResourcePolicy *p) { stop (); ResourcePoliciesGatekeeper::get_instance ().activate_policy (&_history, p); _resource_policy = p; } ResourcePolicy * ConcreteSimulation::get_resource_policy () { return _resource_policy; }