// 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 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/. /* This executable tests for workingness of the SimulationWidget class, * and nothing else. */ #include "gettext.h" #include "sgpemv2/cpu_policies_gatekeeper.hh" #include "sgpemv2/cpu_policy.hh" #include "sgpemv2/cpu_policy_manager.hh" #include "sgpemv2/resource_policies_gatekeeper.hh" #include "sgpemv2/resource_policy.hh" #include "sgpemv2/resource_policy_manager.hh" #include "sgpemv2/history_observer.hh" #include "sgpemv2/scheduler.hh" #include "sgpemv2/simulation.hh" #include "sgpemv2/simulation_observer.hh" #include "sgpemv2/process.hh" #include "sgpemv2/resource.hh" #include "sgpemv2/thread.hh" #include "cairo_elements.hh" #include "cairo_widget.hh" #include "simulation_widget.hh" #include #include #include #include #include #include #include #include #include #include #include #include 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 (guint i = 0; i < sl->size(); i++) { for (guint 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& 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; 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; SimulationWidget _simulation_widget; 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 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"; ResourcePolicyManager & rpm = *ResourcePoliciesGatekeeper::get_instance().get_registered().at(0); Simulation::get_instance().set_resource_policy(rpm.get_avail_policies().at(0)); DummyPolicyManager dummy_manager; const std::vector& 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(Simulation::mode_step_by_step); 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 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? &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, 8, 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"); case Schedulable::state_ready: return Glib::ustring("Schedulable::state_ready"); case Schedulable::state_blocked: return Glib::ustring("Schedulable::state_blocked"); case Schedulable::state_future: return Glib::ustring("Schedulable::state_future"); case Schedulable::state_terminated: return Glib::ustring("Schedulable::state_terminated"); default: return Glib::ustring("Unhandled Schedulable::state!"); } } Glib::ustring get_request_state_name(Request::state st) { switch(st) { case Request::state_unallocable: return Glib::ustring("state_unallocable"); case Request::state_allocated: return Glib::ustring("state_allocated"); case Request::state_future: return Glib::ustring("state_future"); case Request::state_exhausted: return Glib::ustring("state_exhausted"); case Request::state_allocable: return Glib::ustring("state_allocable"); default: return Glib::ustring("Unhandled Request::state!"); } } Glib::ustring get_simulation_state_name(Simulation::state st) { switch(st) { case Simulation::state_running: return Glib::ustring("Simulation::state_running"); case Simulation::state_paused: return Glib::ustring("Simulation::state_paused"); case Simulation::state_stopped: return Glib::ustring("Simulation::state_stopped"); default: return Glib::ustring("Unhandled Simulation state!"); } } // 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::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 Threads; typedef std::vector::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 Requests; typedef std::vector::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 SubRequests; typedef std::vector::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; }