- Added full-featured jumpto command.

- Minor fixes on the gui.


git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@901 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
matrevis 2006-08-18 00:46:38 +00:00
parent d8694b2f5b
commit df4b32f1ba
9 changed files with 339 additions and 68 deletions

View File

@ -187,6 +187,7 @@ src_backend_libbackend_la_SOURCES = \
src/backend/serializer_error.cc \
src/backend/serializers_gatekeeper.cc \
src/backend/simulation.cc \
src/backend/simulation_observer.cc \
src/backend/static_process.cc \
src/backend/static_request.cc \
src/backend/static_resource.cc \
@ -233,6 +234,7 @@ pkginclude_HEADERS += \
src/backend/serializer_error.hh \
src/backend/serializers_gatekeeper.hh \
src/backend/simulation.hh \
src/backend/simulation_observer.hh \
src/backend/sub_request.hh \
src/backend/thread.hh \
src/backend/user_interrupt_exception.hh

View File

@ -13,6 +13,7 @@
<property name="default_height">300</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="icon_name">gtk-preferences</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
@ -551,7 +552,7 @@
<child>
<widget class="GtkVBox" id="Speed.VBox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
@ -651,31 +652,6 @@
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="Spacing.Label">
<property name="visible">True</property>
<property name="label" translatable="yes"></property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>

View File

@ -92,27 +92,6 @@
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="MenuItem.Simulation">
<property name="visible">True</property>
<property name="label" translatable="yes">_Simulation</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="MenuItem.Simulation_menu">
<child>
<widget class="GtkImageMenuItem" id="MenuItem.Simulation.Play">
<property name="visible">True</property>
<property name="label">gtk-media-play</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="MenuItem.Edit">
<property name="visible">True</property>
@ -135,21 +114,38 @@
</child>
<child>
<widget class="GtkMenuItem" id="MenuItem.Help">
<widget class="GtkMenuItem" id="MenuItem.Simulation">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="label" translatable="yes">_Simulation</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="MenuItem.Help_menu">
<widget class="GtkMenu" id="MenuItem.Simulation_menu">
<child>
<widget class="GtkImageMenuItem" id="MenuItem.Help.About">
<widget class="GtkImageMenuItem" id="MenuItem.Simulation.Play">
<property name="visible">True</property>
<property name="label">gtk-about</property>
<property name="label">gtk-media-play</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="pause1">
<property name="visible">True</property>
<property name="label">gtk-media-pause</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="stop1">
<property name="visible">True</property>
<property name="label">gtk-media-stop</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_stop1_activate" last_modification_time="Thu, 17 Aug 2006 21:55:39 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
@ -175,6 +171,27 @@
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="MenuItem.Help">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="MenuItem.Help_menu">
<child>
<widget class="GtkImageMenuItem" id="MenuItem.Help.About">
<property name="visible">True</property>
<property name="label">gtk-about</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>

View File

@ -19,6 +19,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "concrete_simulation.hh"
#include "simulation_observer.hh"
#include "scheduler.hh"
#include "cpu_policies_gatekeeper.hh"
#include <glibmm/timer.h>
@ -27,6 +28,11 @@
#include "smartp.tcc"
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
using namespace std;
using namespace sgpem;
using namespace memory;
@ -34,7 +40,10 @@ using Glib::usleep;
ConcreteSimulation::ConcreteSimulation() :
_state(state_stopped), _mode(true), _timer_interval(1000), _policy(NULL)
{}
{
_notify = false;
_front = 0;
}
void
ConcreteSimulation::set_timer(unsigned int t)
@ -60,6 +69,37 @@ ConcreteSimulation::get_mode() const
return _mode;
}
void
ConcreteSimulation::jump_to(History::position p)
{
switch (_state)
{
case state_running:
pause();
break;
case state_stopped:
_history.reset(true);
_front = 0;
break;
default:
;
}
pause();
bool yet_to_finish = true;
while (yet_to_finish && p > _front)
yet_to_finish = step();
if (!yet_to_finish)
stop();
_history.get_size() << std::endl;
_front = p < _front ? p : _front;
notify_change();
}
void
ConcreteSimulation::pause()
{
@ -81,6 +121,7 @@ ConcreteSimulation::run() throw(UserInterruptException, NullPolicyException, Mal
return;
case state_stopped:
_history.reset(true);
_front = 0;
break;
default:
;
@ -102,8 +143,12 @@ ConcreteSimulation::run() throw(UserInterruptException, NullPolicyException, Mal
try
{
//step forward
bool yet_to_finish = Scheduler::get_instance().step_forward(_history, *get_policy());
bool yet_to_finish = true;
if (_front == get_history().get_size() - 1)
yet_to_finish = Scheduler::get_instance().step_forward(_history, *get_policy());
if (!yet_to_finish) stop();
_front++;
notify_change();
//sleep
Glib::usleep(_timer_interval*1000);
@ -128,7 +173,11 @@ ConcreteSimulation::run() throw(UserInterruptException, NullPolicyException, Mal
{
assert(get_policy() != NULL);
//step forward
bool yet_to_finish = Scheduler::get_instance().step_forward(_history, *get_policy());
bool yet_to_finish = true;
if (_front == get_history().get_size() - 1)
yet_to_finish = Scheduler::get_instance().step_forward(_history, *get_policy());
_front++;
notify_change();
if (yet_to_finish)
pause();
else
@ -142,6 +191,34 @@ ConcreteSimulation::run() throw(UserInterruptException, NullPolicyException, Mal
}
}
bool
ConcreteSimulation::step()
throw(UserInterruptException, NullPolicyException, MalformedPolicyException)
{
if (get_policy() == NULL)
{
stop();
throw NullPolicyException("no policy selected");
}
try
{
assert(get_policy() != NULL);
//step forward
bool yet_to_finish = true;
if (_front == get_history().get_size() - 1)
yet_to_finish = Scheduler::get_instance().step_forward(_history, *get_policy());
_front++;
return yet_to_finish;
}
catch (const CPUPolicyException& e)
{
stop();
throw;
}
}
Simulation::state
ConcreteSimulation::get_state() const
{
@ -154,6 +231,13 @@ ConcreteSimulation::get_history()
return _history;
}
const ConcreteHistory&
ConcreteSimulation::get_history() const
{
return _history;
}
void
ConcreteSimulation::set_policy(CPUPolicy* p) throw(CPUPolicyException)
{

View File

@ -21,9 +21,16 @@
#ifndef CONCRETE_SIMULATION_HH
#define CONCRETE_SIMULATION_HH 1
#include "config.h"
#include "simulation.hh"
#include "concrete_history.hh"
#include <map>
#include <stdexcept>
#include <utility>
#include <vector>
namespace sgpem
{
class ConcreteSimulation;
@ -37,8 +44,12 @@ namespace sgpem
void pause();
void jump_to(History::position p);
void stop();
bool step() throw(UserInterruptException, NullPolicyException, MalformedPolicyException);
void set_timer(const unsigned int);
int get_timer() const;
@ -56,8 +67,11 @@ namespace sgpem
ConcreteHistory& get_history();
const ConcreteHistory& get_history() const;
CPUPolicy* get_policy();
private:
state _state;
bool _mode;

View File

@ -18,11 +18,18 @@
// along with SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "config.h"
#include "simulation.hh"
#include "simulation_observer.hh"
#include "concrete_simulation.hh"
#include <algorithm>
#include <functional>
// Do not include in header file:
#include "singleton.tcc"
using namespace sgpem;
// Explicit template instantiation to allow to export symbols from the DSO.
@ -37,3 +44,47 @@ Simulation::get_instance()
{
return Singleton<ConcreteSimulation>::get_instance();
}
void
Simulation::attach(SimulationObserver& observer)
{
_observers.push_back(&observer);
}
void
Simulation::detach(const SimulationObserver& observer)
{
_observers.erase(std::find(_observers.begin(),
_observers.end(),
&observer));
}
unsigned int Simulation::get_front() const
{
return _front;
}
void
Simulation::notify_change()
{
//if (!_notify) return; // what's the purpose of this?
for (RegisteredObservers::iterator it = _observers.begin();
it != _observers.end(); it++)
(*it)->update(*this);
}
bool
Simulation::set_notify_enabled(bool enabled)
{
bool old_value = _notify;
_notify = enabled;
// Force notify if we re-enable it
if (old_value == false && _notify == true)
notify_change();
return old_value;
}

View File

@ -25,15 +25,17 @@ namespace sgpem
{
class ConcreteSimulation;
class CPUPolicy;
class History;
class SimulationObserver;
}
#include "config.h"
#include "history.hh"
#include "singleton.hh"
#include "user_interrupt_exception.hh"
#include "null_policy_exception.hh"
#include "malformed_policy_exception.hh"
#include <stdexcept>
#include <utility>
#include <vector>
namespace sgpem
@ -97,6 +99,17 @@ namespace sgpem
*/
virtual void stop() = 0;
/**
\brief Jumps the simulation to the specified instant
Pauses the simulation and jumps to the specified instant
*/
virtual void jump_to(History::position p) = 0;
/**
\brief Setter for the attribute timer_interval.
@ -142,11 +155,43 @@ namespace sgpem
virtual History& get_history() = 0;
virtual const History& get_history() const = 0;
virtual unsigned int get_front() const;
/**
* Small kludge to avoid the need for declaration of ConcreteSimulation
* by the calling code of Simulation::get_instance()
*/
static Simulation& get_instance();
virtual void attach(SimulationObserver& observer);
virtual void detach(const SimulationObserver& observer);
/** \brief Enable/disable notifications to registered observers
*
* This is quite useful to disable momentarily notification while you
* do a bunch of insertions and/or deletions in one go, in order to
* speed up things.
*
* \return The old value
*/
virtual bool set_notify_enabled(bool enabled = true);
protected:
typedef std::vector<SimulationObserver*> RegisteredObservers;
RegisteredObservers _observers;
// since no constructor is available, these fields must be defined in concrete subclasses.
bool _notify;
History::position _front;
virtual void notify_change();
private:
};
}

View File

@ -23,6 +23,7 @@
#include "backend/cpu_policy_manager.hh"
#include "backend/policy_parameters.hh"
#include "backend/history.hh"
#include "backend/simulation.hh"
#include "backend/serializers_gatekeeper.hh"
#include "backend/serializer.hh"
#include "backend/static_process.hh"
@ -31,6 +32,7 @@
#include "backend/static_request.hh"
#include "backend/static_sub_request.hh"
#include "backend/concrete_history.hh"
#include "backend/concrete_simulation.hh"
#include "text_simulation.hh"
@ -356,7 +358,7 @@ TextSimulation::on_run(const Tokens& arguments)
check_arguments_num(arguments, 0);
// Listen for updates only during scheduling
Simulation::get_instance().get_history().attach(*this);
Simulation::get_instance().attach(*this);
try
{
@ -393,7 +395,7 @@ TextSimulation::on_run(const Tokens& arguments)
p_stderr(_("\nSimulation is now stopped\n"));
}
Simulation::get_instance().get_history().detach(*this);
Simulation::get_instance().detach(*this);
}
void
@ -404,6 +406,82 @@ TextSimulation::on_pause(const Tokens& arguments)
Simulation::get_instance().pause();
}
void
TextSimulation::on_jumpto(const Tokens& arguments)
{
if (!check_arguments_num(arguments, 1))
return;
// Listen for updates only during scheduling
ustring _position = arguments[0];
History::position p;
try
{
int pos = string_to<int>(_position) + 1;
if (pos < 0)
{
p_stderr(_("ERROR: provided instant is out of range.\n"));
return;
}
p = static_cast<unsigned int>(pos);
}
catch (domain_error e)
{
p_stderr(_("ERROR: provided instant is not a valid integer\n"));
return;
}
catch (out_of_range e)
{
p_stderr(_("ERROR: the instant is not within range.\n")); // does this make sense?
return;
}
Simulation::get_instance().attach(*this);
try
{
Simulation::get_instance().jump_to(p);
}
catch (const UserInterruptException& e)
{
p_stderr(_("ERROR: "));
p_stderr(e.what());
p_stderr(_("\nSimulation is now stopped\n"));
}
catch (const MalformedPolicyException& e)
{
p_stderr(_("ERROR: "));
p_stderr(e.what());
p_stderr(_("\nSimulation is now stopped, and "
"the current policy will be deactivated\n"));
try
{
Simulation::get_instance().set_policy(NULL);
}
catch(const CPUPolicyException& f)
{
// should never happen
p_stderr(_("FATAL ERROR: unable to deactivate the policy: "));
p_stderr(f.what());
abort();
}
}
catch (const NullPolicyException& e)
{
p_stderr(_("ERROR: "));
p_stderr(e.what());
p_stderr(_("\nSimulation is now stopped\n"));
}
Simulation::get_instance().detach(*this);
}
void
TextSimulation::on_stop(const Tokens& arguments)
{
@ -524,6 +602,8 @@ TextSimulation::on_help(const Tokens& arguments)
else if (command == "PAUSE")
p_stdout(_("-- PAUSE COMMAND --\nPauses the simulation. The next call to RUN will "
"continue it.\n"));
else if (command == "JUMPTO")
p_stdout(_("-- JUMPTO COMMAND --\nPauses the simulation and jumps to the specified instant.\n"));
else if (command == "CONFIGURE-CPU-POLICY")
p_stdout(_("-- CONFIGURE-CPU-POLICY COMMAND --\nConfigure parameters exposed by "
"the cpu policy.\n\nThis is currently the only way to control the behaviour of "
@ -1458,6 +1538,7 @@ TextSimulation::parse_command(TextSimulation& sim, const ustring& str)
command_handlers["RUN"] = &TextSimulation::on_run;
command_handlers["STOP"] = &TextSimulation::on_stop;
command_handlers["PAUSE"] = &TextSimulation::on_pause;
command_handlers["JUMPTO"] = &TextSimulation::on_jumpto;
command_handlers["CONFIGURE-CPU-POLICY"] = &TextSimulation::on_configure_cpu_policy;
command_handlers["HELP"] = &TextSimulation::on_help;
command_handlers["GET"] = &TextSimulation::on_get;
@ -1553,7 +1634,7 @@ operator<<(ostream& os, Request::state state)
}
void
TextSimulation::update(const History& changed_history)
TextSimulation::update(const Simulation& changed_simulation)
{
ostringstream oss;
int printed_instant;
@ -1561,10 +1642,10 @@ TextSimulation::update(const History& changed_history)
// Print header for each instant:
if (changed_history.get_size() > 1)
printed_instant = static_cast<int>(changed_history.get_size()) - 2;
if (changed_simulation.get_front() > 1)
printed_instant = static_cast<int>(changed_simulation.get_front()) - 1;
else
printed_instant = -1;
printed_instant = 0;
oss << endl << ">>>> " << printed_instant;
@ -1572,7 +1653,7 @@ TextSimulation::update(const History& changed_history)
// Print ready queue
oss << endl << _("READY QUEUE: { ");
const Environment& env = changed_history.get_last_environment();
const Environment& env = changed_simulation.get_history().get_environment_at(changed_simulation.get_front());
const ReadyQueue& q = env.get_sorted_queue();
for (unsigned int i = 0; i < q.size(); ++i)

View File

@ -28,7 +28,7 @@
#include "templates/smartp.hh"
//#include "backend/policy_parameters.hh"
#include "backend/string_utils.hh"
#include "backend/history_observer.hh"
#include "backend/simulation_observer.hh"
#include "smartp.hh"
@ -53,7 +53,7 @@ namespace sgpem
A command-based interface is used, so methods of the base class can be called with
a proper command string obtained from the input device(s).
*/
class SG_DLLEXPORT TextSimulation : public HistoryObserver
class SG_DLLEXPORT TextSimulation : public SimulationObserver
{
public:
TextSimulation();
@ -71,7 +71,7 @@ namespace sgpem
Prints the actual state of the simulation, with emphasis on the current
status of the scheduling process (ready queue and running process).
*/
virtual void update(const History& changed_history);
virtual void update(const Simulation& changed_simulation);
bool check_arguments_num(const Tokens& arguments, unsigned int num);
bool unsaved_ask_confirm() const;
@ -81,6 +81,7 @@ namespace sgpem
void get_parameter(CommandParameter<T>& parameter);
void on_run(const Tokens& arguments);
void on_pause(const Tokens& arguments);
void on_jumpto(const Tokens& arguments);
void on_stop(const Tokens& arguments);
void on_configure_cpu_policy(const Tokens& arguments);
void on_help(const Tokens& arguments);