sgpemv2/src/testsuite/test-simulation_widget.cc

684 lines
19 KiB
C++

// src/testsuite/test-history.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
/* This executable tests for workingness of the SimulationWidget class,
* and nothing else. */
#include "config.h"
#include "gettext.h"
#include <glibmm/main.h>
#include <glibmm/module.h>
#include <glibmm/ustring.h>
#include <glibmm/thread.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/main.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/window.h>
#include <cassert>
#include <iostream>
#include "backend/cpu_policies_gatekeeper.hh"
#include "backend/cpu_policy.hh"
#include "backend/cpu_policy_manager.hh"
#include "backend/history_observer.hh"
#include "backend/scheduler.hh"
#include "backend/simulation.hh"
#include "backend/simulation_observer.hh"
#include "backend/process.hh"
#include "backend/resource.hh"
#include "backend/thread.hh"
#include "cairo_elements.hh"
#include "cairo_widget.hh"
#include "simulation_widget.hh"
using namespace sgpem;
using namespace std;
using Glib::ustring;
// ------------------------------------------------------
//
// PRRPolicy class
//
// ------------------------------------------------------
/** An hard-coded Priority Round Robin policy
* it adds a new constructor taking the quantum size (time slice)*/
class PRRPolicy : public CPUPolicy
{
public:
PRRPolicy()
{
_instance = this;
}
PRRPolicy(int quantum) : _quantum(quantum)
{
_instance = this;
}
static PRRPolicy& get_instance()
{
if (!_instance) _instance = new PRRPolicy(3); // quantum size
return *_instance;
}
virtual ~PRRPolicy()
{}
virtual void configure() throw(UserInterruptException, MalformedPolicyException)
{}
virtual void sort_queue() const throw(UserInterruptException)
{ // here a lot of fun, exactly O(n^2) fun!
// ReadyQueue sl = History.get_instance().get_simulation_status_at(get_current_time());
ReadyQueue* sl = Scheduler::get_instance().get_ready_queue();
if(sl && sl->size()>=2)
{
for (int i = 0; i < sl->size(); i++)
{
for (int j = 0; j < sl->size() - 1; j++)
{
if ( (sl->get_item_at(j).get_current_priority() < sl->get_item_at(j + 1).get_current_priority())
|| ((sl->get_item_at(j).get_current_priority() == sl->get_item_at(j + 1).get_current_priority())
&& (sl->get_item_at(j).get_last_acquisition() > sl->get_item_at(j + 1).get_last_acquisition())) )
{
sl->swap(j, j + 1);
}
}
}
}
}
/*
int get_id() const
{
return 42;
}
*/
virtual Glib::ustring get_description() const
{
return "42";
}
virtual Glib::ustring get_name() const
{
return "FourtyTwo";
}
virtual bool is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException)
{
return true;
}
virtual int get_time_slice() const throw(UserInterruptException, MalformedPolicyException)
{
return _quantum;
}
PolicyParameters& get_parameters()
{
return _parameters;
}
virtual void activate() throw(UserInterruptException, MalformedPolicyException)
{
}
virtual void deactivate()
{
}
protected:
PolicyParameters _parameters;
// int _id;
int _quantum;
private:
static PRRPolicy* _instance;
};
PRRPolicy* PRRPolicy::_instance=0;
// ------------------------------------------------------
//
// DummyPolicyManager class
//
// ------------------------------------------------------
class DummyPolicyManager : public CPUPolicyManager
{
public:
/** \brief CPUPolicyManager constructor
*
* Saves ``this'' pointer into the _registered attribute, so it can access
* it when requested. This is done so that concrete subclasses can be defined
* even if they are found in external dynamic modules not known at compile time.
*
* For the moment, just an instance of CPUPolicyManager can be saved. This will
* be expanded in next milestones.
*/
DummyPolicyManager()
{
_policies.push_back(new PRRPolicy);
}
virtual ~DummyPolicyManager()
{
}
/**
Gets THE policy (the only today) used.
Next versions will implement some other kind.
\return A reference to the policy.
FIXME deprecated
*/
//virtual CPUPolicy& get_policy() = 0;
/**
Init (or reset if yet initialized) the manager.
FIXME deprecated
*/
virtual void init()
{
}
virtual const std::vector<CPUPolicy*>& get_avail_policies()
{
return _policies;
}
protected:
virtual void collect_policies()
{
}
};
// ------------------------------------------------------
//
// MainWindow class
//
// contains and controls the tested widget
//
// ------------------------------------------------------
class MainWindow : public Gtk::Window
{
public:
MainWindow(Simulation& simulation);
virtual ~MainWindow();
protected:
virtual void on_button_start_clicked();
virtual void on_button_stop_clicked();
virtual void on_button_pause_clicked();
virtual void on_button_runmode_clicked();
virtual bool on_timer_timeout();
// TestWidget _test_widget;
SimulationWidget _simulation_widget;
Gtk::Button _start_button;
Gtk::Button _stop_button;
Gtk::Button _pause_button;
Gtk::CheckButton _runmode_button;
Gtk::HBox _buttons_box;
Gtk::VBox _main_box;
Gtk::ScrolledWindow _scroller;
Simulation::state _sim_state;
};
MainWindow::MainWindow(Simulation& simulation)
: _start_button("Start"),
_stop_button("Stop"),
_pause_button("Pause"),
_runmode_button("Continue"),
_simulation_widget(simulation),
_sim_state(Simulation::state_stopped)
{
// This just sets the title of our new window.
set_title("Simulation Widget Test");
add(_main_box);
_buttons_box.pack_start(_start_button);
_start_button.show();
_buttons_box.pack_start(_stop_button);
_stop_button.show();
_buttons_box.pack_start(_pause_button);
_pause_button.show();
_buttons_box.pack_start(_runmode_button);
_runmode_button.set_active(false);
_runmode_button.show();
_main_box.pack_start(_buttons_box, Gtk::PACK_SHRINK);
_buttons_box.show();
// _main_box.pack_start(_test_widget);
// _test_widget.show();
_scroller.add(_simulation_widget);
_scroller.show();
_main_box.pack_start(_scroller);
_simulation_widget.show();
_main_box.show();
// Simulation::get_instance().attach(_simulation_widget);
/*
_start_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_start_clicked) );
_stop_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_stop_clicked) );
_pause_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_pause_clicked) );
_runmode_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_runmode_clicked) );
*/
// connect after standard signal handler
_start_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_start_clicked), true );
_stop_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_stop_clicked), true );
_pause_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_pause_clicked), true );
_runmode_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_runmode_clicked), true );
Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::on_timer_timeout), 1000);
//is equivalent to:
/*
const Glib::RefPtr<Glib::TimeoutSource> timeout_source = Glib::TimeoutSource::create(1000);
timeout_source->connect(sigc::ptr_fun(&timeout_handler));
timeout_source->attach(Glib::MainContext::get_default());
*/
}
MainWindow::~MainWindow()
{
}
void MainWindow::on_button_start_clicked()
{
if(_sim_state == Simulation::state_stopped
|| _sim_state == Simulation::state_paused)
{
if(!_runmode_button.get_active())
{
// one step - drive directly simulation
Simulation& simu = Simulation::get_instance();
simu.run();
_sim_state = simu.get_state();
// _simulation_widget.redraw();
}
else
{
_sim_state = Simulation::state_running;
}
}
}
void MainWindow::on_button_stop_clicked()
{
if(_sim_state == Simulation::state_running
|| _sim_state == Simulation::state_paused)
{
_sim_state = Simulation::state_stopped;
Simulation::get_instance().stop();
// _simulation_widget.redraw();
}
}
void MainWindow::on_button_pause_clicked()
{
if(_sim_state == Simulation::state_running)
{
_sim_state = Simulation::state_paused;
}
else if(_sim_state == Simulation::state_paused)
{
_sim_state = Simulation::state_running;
}
}
void MainWindow::on_button_runmode_clicked()
{
}
bool MainWindow::on_timer_timeout()
{
// std::cout << "Timer sim stat= " << _sim_state << endl;
if(_sim_state == Simulation::state_running)
{
Simulation& simu = Simulation::get_instance();
simu.run();
// _simulation_widget.redraw();
if(simu.get_state()==Simulation::state_stopped)
_sim_state = Simulation::state_stopped;
}
return true;
}
// utility functions...
// insert some resources, processes, threads, requests, subrequests
void fillHistory(History &hist);
// print entire environment into the passed ostream
void dumpEnvironment(const Environment& env, ostream &os);
// return the Schedulable::state readable string
Glib::ustring get_schedulable_state_name(Schedulable::state st);
// return the Request::state readable string
Glib::ustring get_request_state_name(Request::state st);
// return the Simulation::state readable string
Glib::ustring get_simulation_state_name(Simulation::state st);
// ------------------------------------------------------
//
// MainWindow class
//
// ------------------------------------------------------
int
main(int argc, char** argv)
{
ostream& info = cout;
ostream& test = cerr;
Gtk::Main kit(argc, argv);
// Set up Glib thread support
Glib::thread_init();
info << "test-holt - start \n";
Simulation& simu = Simulation::get_instance();
info << "gets simulation \n";
History& hist = Simulation::get_instance().get_history();
info << "gets history \n";
DummyPolicyManager dummy_manager;
const std::vector<CPUPolicy*>& policies = dummy_manager.get_avail_policies();
CPUPolicy* pol = policies[0];
info << "policy " << pol->get_name() << endl;
fillHistory(hist);
info << "history filled \n";
simu.set_policy(pol);
info << "policy activated \n";
simu.set_mode(false);
simu.set_timer(0);
info << "simulation set_mode single step\n";
info << "START environment dump \n";
dumpEnvironment(hist.get_last_environment(), info);
info << "END environment dump \n";
info << "simulation state: " << get_simulation_state_name(simu.get_state()) << endl;
MainWindow win(simu);
win.set_border_width(10);
win.resize (400, 200);
Gtk::Main::run(win);
return 0;
}
// insert some resources, processes, threads, requests, subrequests
void fillHistory(History &hist)
{
// insert resources to delete soon
// this create a numbering of keys starting from 2...
// serves to prove correct save/restore independent from key numbering
// add a resource - name, preemptable, places, availability
History::ResourcePair respair0 = hist.add_resource(Glib::ustring("Resource 0"), false, 1, 2);
// add a resource - name, preemptable, places, availability
History::ResourcePair respair00 = hist.add_resource(Glib::ustring("Resource 00"), false, 1, 2);
// add a resource - name, preemptable, places, availability
History::ResourcePair respair = hist.add_resource(Glib::ustring("Resource 1"), false, 1, 2);
// add a resource - name, preemptable, places, availability
History::ResourcePair respair2 = hist.add_resource(Glib::ustring("Invalid? Resource <n> 1"), false, 1, 2);
// delete resources to kreate a key numbering hole
hist.remove(respair0.first);
hist.remove(respair00.first);
// add a process - name, arrival time, priority
Process& p1 = hist.add_process(Glib::ustring("Process 1"), 0, 2); // name, arrival time, priority
// add a process - name, arrival time, priority
Process& p2 = hist.add_process(Glib::ustring("Process 2"), 7, 3); // name, arrival time, priority
// add a process - name, arrival time, priority
Process& p3 = hist.add_process(Glib::ustring("Process 3"), 5, 5); // name, arrival time, priority
// add a process - name, arrival time, priority
Process& p4 = hist.add_process(Glib::ustring("Invalid? <process/> &3 or\\4"), 9, 1); // name, arrival time, priority
// add a thread - name, parent, cpu time, arrival time, priority
Thread& p1_t1 = hist.add_thread(Glib::ustring("P1 - Thread 1"), p1, 14, 0, 2);
// add a thread - name, parent, cpu time, arrival time, priority
// Thread& p1_t2 = hist.add_thread(Glib::ustring("P1 - Thread 2"), p1, 3, 0, 5);
// add a thread - name, parent, cpu time, arrival time, priority
Thread& p2_t1 = hist.add_thread(Glib::ustring("P2 - Thread 1"), p2, 20, 0, 2);
// add a thread - name, parent, cpu time, arrival time, priority
Thread& p3_t1 = hist.add_thread(Glib::ustring("P3 - Thread 2"), p3, 12, 0, 2);
// add a thread - name, parent, cpu time, arrival time, priority
Thread& p4_t1 = hist.add_thread(Glib::ustring("P4 - Thread 1"), p4, 3, 0, 2);
// add a request - Thread, time
Request& req1 = hist.add_request(p1_t1, 3);
// add a sub request - Request, resource_key, duration, places
SubRequest& req1_sub1 = hist.add_subrequest(req1, respair.first, 6);
// add a request - Thread, time
Request& req2 = hist.add_request(p2_t1, 1);
// add a sub request - Request, resource_key, duration, places
SubRequest& req2_sub1 = hist.add_subrequest(req2, respair.first, 4);
// add a request - Thread, time
Request& req3 = hist.add_request(p3_t1, 0);
// add a sub request - Request, resource_key, duration, places
SubRequest& req3_sub1 = hist.add_subrequest(req3, respair.first, 5);
// add a request - Thread, time
Request& req3bis = hist.add_request(p3_t1, 7);
// add a sub request - Request, resource_key, duration, places
SubRequest& req3bis_sub1 = hist.add_subrequest(req3bis, respair.first, 5);
}
Glib::ustring get_schedulable_state_name(Schedulable::state st)
{
switch(st)
{
case Schedulable::state_running:
return Glib::ustring("Schedulable::state_running");
break;
case Schedulable::state_ready:
return Glib::ustring("Schedulable::state_ready");
break;
case Schedulable::state_blocked:
return Glib::ustring("Schedulable::state_blocked");
break;
case Schedulable::state_future:
return Glib::ustring("Schedulable::state_future");
break;
case Schedulable::state_terminated:
return Glib::ustring("Schedulable::state_terminated");
break;
}
}
Glib::ustring get_request_state_name(Request::state st)
{
switch(st)
{
case Request::state_unallocable:
return Glib::ustring("state_unallocable");
break;
case Request::state_allocated:
return Glib::ustring("state_allocated");
break;
case Request::state_future:
return Glib::ustring("state_future");
break;
case Request::state_exhausted:
return Glib::ustring("state_exhausted");
break;
case Request::state_allocable:
return Glib::ustring("state_allocable");
break;
}
}
Glib::ustring get_simulation_state_name(Simulation::state st)
{
switch(st)
{
case Simulation::state_running:
return Glib::ustring("Simulation::state_running");
break;
case Simulation::state_paused:
return Glib::ustring("Simulation::state_paused");
break;
case Simulation::state_stopped:
return Glib::ustring("Simulation::state_stopped");
break;
}
}
// print entire environment into the passed ostream
void dumpEnvironment(const Environment& env, ostream &os)
{
os << "dump environment start " << endl;
const Environment::Resources& rvect = env.get_resources();
typedef Environment::Resources::const_iterator res_iterator;
res_iterator riter = rvect.begin();
while (riter != rvect.end())
{
Resource* r = (*riter).second;
os << " resource name: " << r->get_name()
/* << " key: " << (*riter).first */
<< " places: " << r->get_places() << endl;
riter++;
}
const Environment::Processes& pvect = env.get_processes();
typedef std::vector<Process*>::const_iterator proc_iterator;
proc_iterator iter = pvect.begin();
proc_iterator end = pvect.end();
while (iter != end)
{
Process* p = (*iter);
os << " process name: " << p->get_name()
<< " arrival_time: " << p->get_arrival_time()
<< " base_priority: " << p->get_base_priority()
<< " " << get_schedulable_state_name(p->get_state())
<< endl;
iter++;
typedef std::vector<Thread*> Threads;
typedef std::vector<Thread*>::const_iterator thr_iterator;
const Threads& tvect = p->get_threads();
thr_iterator iter1 = tvect.begin();
thr_iterator end1 = tvect.end();
while (iter1 != end1)
{
Thread* t = (*iter1);
os << " thread name: " << t->get_name()
<< " arrival_time: " << t->get_arrival_time()
<< " base_priority: " << t->get_base_priority()
<< " " << get_schedulable_state_name(t->get_state())
<< endl;
typedef std::vector<Request*> Requests;
typedef std::vector<Request*>::const_iterator req_iterator;
const Requests& rvect = t->get_requests();
req_iterator iter2 = rvect.begin();
req_iterator end2 = rvect.end();
while (iter2 != end2)
{
Request* r = (*iter2);
os << " request arrival_time: " << r->get_instant() << endl;
typedef std::vector<SubRequest*> SubRequests;
typedef std::vector<SubRequest*>::const_iterator subreq_iterator;
const SubRequests& srvect = r->get_subrequests();
subreq_iterator iter3 = srvect.begin();
subreq_iterator end3 = srvect.end();
while (iter3 != end3)
{
SubRequest* sr = (*iter3);
os << " sub request: " /* << " resource_key: " << sr->get_resource_key() */;
Environment::Resources::const_iterator pos = env.get_resources().find(sr->get_resource_key());
if (pos != env.get_resources().end())
{
os << " name: " << pos->second->get_name();
}
os << " length: " << sr->get_length()
<< " " << get_request_state_name(sr->get_state())
<< endl;
iter3++;
}
iter2++;
}
iter1++;
}
}
os << "dump environment end " << endl << endl;
}