sgpemv2/src/holt_widget.cc

757 lines
20 KiB
C++
Raw Normal View History

// src/simulation_widget.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
#include "cairo_elements.hh"
#include "backend/history.hh"
#include "backend/schedulable.hh"
#include "backend/resource.hh"
#include "backend/simulation.hh"
#include "backend/string_utils.hh"
#include "backend/thread.hh"
#include "holt_widget.hh"
#include <math.h>
#include <iostream>
#include <cassert>
#ifndef NDEBUG
#include <iostream>
#endif
using namespace sgpem;
using namespace std;
HoltNode::HoltNode(Vec2 pt)
: _radius(20)
{
//_x = pt.real(); _y = pt.imag();
_pos = pt;
}
HoltNode::~HoltNode()
{
}
Vec2 HoltNode::set_position(Vec2 pt)
{
Vec2 pt_old = _pos;
_pos = pt;
return pt_old;
}
Vec2 HoltNode::get_position()
{
return _pos;
}
double HoltNode::set_radius(double radius)
{
double old_rad = _radius;
_radius = radius;
return old_rad;
}
double HoltNode::get_radius()
{
return _radius;
}
// double HoltNode::_radius = 20;
HoltResource::HoltResource(const Resource& resource, resource_key_t resource_key, Vec2 pt)
: HoltNode(pt)
{
_resource = &resource;
_resource_key = resource_key;
}
HoltResource::~HoltResource()
{
}
void HoltResource::draw(cairo_t *cr)
{
// draw rectangle
cairo_rectangle(cr,
_pos.real() - _radius, _pos.imag() - _radius,
2*_radius, 2*_radius);
// fill
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_fill_preserve (cr);
// outline
cairo_set_source_rgb (cr, 0, 0, 0);
// clip text outside region
cairo_clip_preserve (cr);
// draw text
cairo_text_extents_t extents;
cairo_text_extents(cr, _resource->get_name().c_str(), &extents);
// cairo_move_to(cr, xpos - _radius, ypos - _radius + extents.height);
cairo_move_to(cr, _pos.real() - extents.width/2, _pos.imag() + extents.height/2);
cairo_show_text(cr, _resource->get_name().c_str());
cairo_reset_clip (cr); // reset clip region
// stroke all
cairo_stroke (cr);
}
Vec2 HoltResource::get_intersection_to(Vec2 pt)
{
Vec2 final = _pos;
Vec2 segment = pt - _pos;
double len = std::abs(segment);
if(len>0)
{
// segment to unary modulus vector (versor)
segment /= len;
if(abs(segment.real())>=M_SQRT1_2)
{
// direction East(>0) or West(<0)
segment *= _radius/abs(segment.real());
}
else
{
// direction North(<0) or South(>0)
segment *= _radius/abs(segment.imag());
}
final = _pos + segment;
}
return final;
}
HoltSchedulable::HoltSchedulable(const Schedulable& schedulable, Vec2 pt)
: HoltNode(pt)
{
_schedulable = &schedulable;
}
HoltSchedulable::~HoltSchedulable()
{
}
void HoltSchedulable::draw(cairo_t *cr)
{
cairo_save(cr); // save context state
cairo_pattern_t* gradient;
gradient = cairo_pattern_create_radial( _pos.real(), _pos.imag(), 0.0, _pos.real(), _pos.imag(), _radius);
/*
_ready_process_gradient = cairo_pattern_create_linear(0, 0, 0, _yu_process_bar_height * _y_unit);
// yellow
cairo_pattern_add_color_stop_rgba(_ready_process_gradient, 0.00, 1.0, 1.0, 0.5, 0.7);
cairo_pattern_add_color_stop_rgba(_ready_process_gradient, 1.00, 1.0, 1.0, 0.0, 1.0);
_running_process_gradient = cairo_pattern_create_linear(0, 0, 0, _yu_process_bar_height * _y_unit);
// green
cairo_pattern_add_color_stop_rgba(_running_process_gradient, 0.00, 0.5, 1.0, 0.5, 0.7);
cairo_pattern_add_color_stop_rgba(_running_process_gradient, 1.00, 0.0, 1.0, 0.0, 1.0);
_blocked_process_gradient = cairo_pattern_create_linear(0, 0, 0, _yu_process_bar_height * _y_unit);
// blue
cairo_pattern_add_color_stop_rgba(_blocked_process_gradient, 0.00, 0.5, 0.5, 1.0, 0.7);
cairo_pattern_add_color_stop_rgba(_blocked_process_gradient, 1.00, 0.0, 0.0, 1.0, 1.0);
*/
// draw circle
cairo_arc (cr, _pos.real(), _pos.imag(), _radius, 0, 2 * M_PI);
// filling
switch(_schedulable->get_state())
{
case Schedulable::state_running:
// cairo_set_source_rgb (cr, 0, 1, 0);
// green
cairo_pattern_add_color_stop_rgba(gradient, 0.00, 0.5, 1.0, 0.5, 0.7);
cairo_pattern_add_color_stop_rgba(gradient, 1.00, 0.0, 1.0, 0.0, 1.0);
cairo_set_source(cr, gradient);
break;
case Schedulable::state_ready:
// cairo_set_source_rgb (cr, 1, 1, 0);
// yellow
cairo_pattern_add_color_stop_rgba(gradient, 0.00, 1.0, 1.0, 0.5, 0.7);
cairo_pattern_add_color_stop_rgba(gradient, 1.00, 1.0, 1.0, 0.0, 1.0);
cairo_set_source(cr, gradient);
break;
case Schedulable::state_blocked:
// cairo_set_source_rgb (cr, 1, 0, 0);
// blue
cairo_pattern_add_color_stop_rgba(gradient, 0.00, 0.5, 0.5, 1.0, 0.7);
cairo_pattern_add_color_stop_rgba(gradient, 1.00, 0.0, 0.0, 1.0, 1.0);
cairo_set_source(cr, gradient);
break;
case Schedulable::state_future:
//cairo_set_source_rgb (cr, 0.5, 0.5, 1);
break;
case Schedulable::state_terminated:
cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
break;
}
cairo_fill_preserve (cr);
// outline
cairo_set_source_rgb (cr, 0, 0, 0);
// clip text outside region
cairo_clip_preserve (cr);
// draw text
cairo_text_extents_t extents;
cairo_text_extents(cr, _schedulable->get_name().c_str(), &extents);
// cairo_move_to(cr, xpos - _radius, ypos - _radius + extents.height);
cairo_move_to(cr, _pos.real() - extents.width/2, _pos.imag() + extents.height/2);
cairo_show_text(cr, _schedulable->get_name().c_str());
cairo_reset_clip (cr); // reset clip region
// stroke all
cairo_stroke (cr);
cairo_restore(cr); // restore context state
cairo_pattern_destroy(gradient);
}
Vec2 HoltSchedulable::get_intersection_to(Vec2 pt)
{
Vec2 final = _pos;
Vec2 segment = pt - _pos;
double len = std::abs(segment);
if(len>0)
{
segment *= _radius/len;
final = _pos + segment;
}
return final;
}
HoltRequest::HoltRequest(HoltSchedulable& hp, HoltResource& hr, Request::state state)
: _hp(&hp),
_hr(&hr),
_state(state)
{
}
HoltRequest::~HoltRequest()
{
}
void HoltRequest::draw(cairo_t *cr)
{
Vec2 resource = _hp->get_intersection_to(_hr->get_position());
Vec2 schedulable = _hr->get_intersection_to(_hp->get_position());
cairo_save(cr);
// cairo_set_line_width(cr, 0.5*cairo_get_line_width(cr));
switch(_state)
{
case Request::state_unallocable:
// blue
cairo_set_source_rgb(cr, 0, 0, 1);
arrow(cr, schedulable, resource);
break;
case Request::state_allocated:
// green
cairo_set_source_rgb(cr, 0, 1, 0);
arrow(cr, resource, schedulable);
break;
case Request::state_future:
break;
case Request::state_exhausted:
break;
case Request::state_allocable:
// yellow
cairo_set_source_rgb(cr, 1, 1, 0);
arrow(cr, schedulable, resource);
break;
}
// stroke all
cairo_stroke (cr);
cairo_restore(cr);
}
void HoltRequest::arrow(cairo_t *cr, Vec2 first, Vec2 second)
{
cairo_move_to(cr, second.real(), second.imag());
cairo_line_to(cr, first.real(), first.imag());
Vec2 arrowside = second-first;
arrowside *= 10.0/std::abs(arrowside);
Vec2 deviation(5.0, 1.0); deviation /= std::abs(deviation);// = std::polar(1,M_PI/6.0);
Vec2 side1 = arrowside * deviation;
Vec2 side2 = arrowside * conj(deviation);
cairo_move_to(cr, first.real(), first.imag());
cairo_line_to(cr, first.real()+side1.real(), first.imag()+side1.imag());
cairo_move_to(cr, first.real(), first.imag());
cairo_line_to(cr, first.real()+side2.real(), first.imag()+side2.imag());
}
HoltWidget::HoltWidget(Simulation& simulation)
: Glib::ObjectBase("sgpem_HoltWidget"),
CairoWidget(),
SimulationObserver(),
HistoryObserver(),
_simulation(&simulation),
_n_proc(0),
_n_res(0),
_radius(20),
_show_threads(false),
_arrange_mode(arrange_horizontal)
{
// Register this SimulationObserver:
_simulation->attach(*this);
// Register this HistoryObserver:
_simulation->get_history().attach(*this);
}
HoltWidget::~HoltWidget()
{
// Unregister this HistoryObserver:
_simulation->get_history().detach(*this);
// Unregister this SimulationObserver:
_simulation->detach(*this);
}
double
HoltWidget::get_radius()
{
return _arrange_mode;
}
double
HoltWidget::set_radius(double radius)
{
double old_radius = _radius;
if(radius>0)
_radius = radius;
// resize_redraw();
return old_radius;
}
HoltWidget::arrange_mode
HoltWidget::get_arrange_mode()
{
return _arrange_mode;
}
HoltWidget::arrange_mode
HoltWidget::set_arrange_mode(arrange_mode mode)
{
arrange_mode old_mode = _arrange_mode;
_arrange_mode = mode;
arrange();
// resize_redraw();
return old_mode;
}
void
HoltWidget::arrange()
{
std::cout << "HoltWidget::arrange" << endl;
// cout << "START:" << endl;
// _x_req = 0;
// _y_req = 0;
Vec2 pos, inc, mul, cen;
if(_arrange_mode==arrange_horizontal)
{
pos = Vec2(2*_radius, 2*_radius);
inc = Vec2(3*_radius, 0);
}
else if(_arrange_mode==arrange_vertical)
{
pos = Vec2(2*_radius, 2*_radius);
inc = Vec2(0, 3*_radius);
}
else // _arrange_mode==arrange_circular
{
int sx = _draw_w; // get_width();
int sy = _draw_h; // get_height();
int nelem = _holt_resources.size()+_holt_schedulables.size();
if(sx<=sy)
inc = Vec2(sx/2-2*_radius, 0);
else
inc = Vec2(sy/2-2*_radius, 0);
if(nelem>0)
mul = Vec2(cos(2*M_PI/(double)nelem), sin(2*M_PI/(double)nelem));
else
mul = Vec2(0,0);
// cen = Vec2(sx/2, sy/2);
cen = Vec2(2*_radius+inc.real(), 2*_radius+inc.real());
pos = inc + cen;
// cout << "A) pos=" << pos << " cen=" << cen << " inc=" << inc << " mul=" << mul << endl;
}
HoltResources::const_iterator riter = _holt_resources.begin();
while(riter!=_holt_resources.end())
{
HoltResource* hr = (*riter).second;
// cout << "r-A) pos=" << pos << " cen=" << cen << " inc=" << inc << " mul=" << mul << endl;
hr->set_position(pos);
hr->set_radius(_radius);
/*
if(pos.real()+_radius>_x_req)
_x_req = pos.real()+_radius;
if(pos.imag()+_radius>_y_req)
_y_req = pos.imag()+_radius;
*/
if(_arrange_mode!=arrange_circular)
{
pos += inc;
}
else // _arrange_mode==arrange_circular
{
inc *= mul;
pos = cen + inc;
}
riter++;
// cout << "r-B) pos=" << pos << " cen=" << cen << " inc=" << inc << " mul=" << mul << endl;
}
if(_arrange_mode==arrange_horizontal)
{
pos = Vec2(2*_radius, 8*_radius);
inc = Vec2(3*_radius, 0);
}
else if(_arrange_mode==arrange_vertical)
{
pos = Vec2(8*_radius, 2*_radius);
inc = Vec2(0, 3*_radius);
}
typedef HoltProcesses::const_iterator holt_proc_iterator;
holt_proc_iterator piter = _holt_schedulables.begin();
while(piter!=_holt_schedulables.end())
{
HoltSchedulable* hp = (*piter);
// cout << "p-A) pos=" << pos << " cen=" << cen << " inc=" << inc << " mul=" << mul << endl;
hp->set_position(pos);
hp->set_radius(_radius);
/*
if(pos.real()+_radius>_x_req)
_x_req = pos.real()+_radius;
if(pos.imag()+_radius>_y_req)
_y_req = pos.imag()+_radius;
*/
if(_arrange_mode!=arrange_circular)
{
pos += inc;
}
else // _arrange_mode==arrange_circular
{
inc *= mul;
pos = cen + inc;
}
// cout << "p-B) pos=" << pos << " cen=" << cen << " inc=" << inc << " mul=" << mul << endl;
piter++;
}
}
bool
HoltWidget::get_show_threads()
{
return _show_threads;
}
bool
HoltWidget::set_show_threads(bool show)
{
bool old_show = _show_threads;
_show_threads = show;
// resize_redraw();
return old_show;
}
void
HoltWidget::update(const Simulation& changed_simulation)
{
std::cout << "HoltWidget::update - Simulation" << endl;
// Force redraw
//redraw();
acquire();
resize_redraw();
}
void
HoltWidget::update(const History& changed_history)
{
std::cout << "HoltWidget::update - History" << endl;
// Force redraw
//redraw();
//acquire();
//resize_redraw();
}
void
HoltWidget::acquire()
{
std::cout << "HoltWidget::acquire" << endl;
_holt_resources.clear();
_holt_schedulables.clear();
_holt_requests.clear();
_n_res = _n_proc = 0;
const History& hist = _simulation->get_history();
const Environment& env = hist.get_last_environment();
Vec2 pos(2*_radius, 2*_radius);
const Environment::Resources& rvect = env.get_resources();
Environment::Resources::const_iterator riter = rvect.begin();
while(riter!=rvect.end())
{
resource_key_t index = (*riter).first;
Resource* r = (*riter).second;
HoltResource *hr = new HoltResource(*r, index, pos);
HoltResources::iterator temp = _holt_resources.insert(std::pair<resource_key_t,HoltResource*>(index, hr)).first;
_n_res++;
riter++;
pos += Vec2(4*_radius, 0);
}
pos = Vec2(2*_radius, 8*_radius);
// iter trough processes
const Environment::Processes& pvect = env.get_processes();
Environment::Processes::const_iterator proc_iter = pvect.begin();
while(proc_iter!=pvect.end())
{
Process* p = (*proc_iter);
proc_iter++;
Schedulable::state proc_state = p->get_state();
if(proc_state==Schedulable::state_running
|| proc_state==Schedulable::state_ready
|| proc_state==Schedulable::state_blocked )
{
_n_proc++;
HoltSchedulable *hp;
if(!_show_threads)
{
hp = new HoltSchedulable(*p, pos);
_holt_schedulables.push_back(hp);
pos += Vec2(4*_radius, 0);
}
// iter trough threads, requests, subrequests
// FIXME
// typedef std::vector<Thread*> Threads;
// typedef std::vector<Thread*>::const_iterator thr_iterator;
const std::vector<Thread*>& tvect = p->get_threads();
std::vector<Thread*>::const_iterator thr_iter = tvect.begin();
while(thr_iter!=tvect.end())
{
Thread* t = (*thr_iter);
thr_iter++;
/*
os << " thread name: " << t->get_name()
<< " arrival_time: " << t->get_arrival_time()
<< " base_priority: " << t->get_base_priority() << endl;
*/
Schedulable::state thr_state = t->get_state();
if(thr_state==Schedulable::state_running
|| thr_state==Schedulable::state_ready
|| thr_state==Schedulable::state_blocked )
{
if(_show_threads)
{
hp = new HoltSchedulable(*t, pos);
_holt_schedulables.push_back(hp);
pos += Vec2(4*_radius, 0);
}
// iter trough requests
const std::vector<Request*>& rvect = t->get_requests();
std::vector<Request*>::const_iterator req_iter = rvect.begin();
while(req_iter!=rvect.end())
{
Request* r = (*req_iter);
req_iter++;
// os << " request arrival_time: " << r->get_instant() << endl;
// iter trough subrequests
const std::vector<SubRequest*>& srvect = r->get_subrequests();
std::vector<SubRequest*>::const_iterator subr_iter = srvect.begin();
while(subr_iter!=srvect.end())
{
SubRequest* sr = (*subr_iter);
subr_iter++;
// os << " sub request: " /* << " resource_key: " << sr->get_resource_key() */;
Request::state subr_state = sr->get_state();
if(subr_state==Request::state_unallocable
|| subr_state==Request::state_allocated
|| subr_state==Request::state_allocable )
{
Environment::Resources::const_iterator pos = env.get_resources().find(sr->get_resource_key());
HoltResources::const_iterator hpos = _holt_resources.find(sr->get_resource_key());
if (pos != env.get_resources().end() && hpos!=_holt_resources.end())
{
// associates process (or thread) with resource)
HoltRequest *hreq = new HoltRequest(*hp, *(hpos->second), sr->get_state());
_holt_requests.push_back(hreq);
// cout << "added HoltRequest\n"
// os << " name: " << pos->second->get_name();
}
} // ~ if(subr_state==Request::state_unallocable ... etc
/*
os << " length: " << sr->get_length();
os << " state: " << sr->get_state() << endl;
*/
} // ~ while(subr_iter!=srvect.end())
} // ~ while(req_iter!=rvect.end())
} // ~ if(thr_state==Schedulable::state_running ...
} // ~ while(thr_iter!=tvect.end())
} // ~ if(proc_state==Schedulable::state_running ...etc
}
// arrange();
}
void
HoltWidget::draw_widget(cairo_t* ctx)
{
std::cout << "HoltWidget::draw_widget" << endl;
arrange();
typedef HoltResources::const_iterator holt_res_iterator;
holt_res_iterator riter = _holt_resources.begin();
while(riter!=_holt_resources.end())
{
HoltResource* hr = (*riter).second;
hr->draw(ctx);
riter++;
}
typedef HoltProcesses::const_iterator holt_proc_iterator;
holt_proc_iterator piter = _holt_schedulables.begin();
while(piter!=_holt_schedulables.end())
{
HoltSchedulable* hp = (*piter);
hp->draw(ctx);
piter++;
}
typedef HoltRequests::const_iterator holt_requ_iterator;
holt_requ_iterator reqiter = _holt_requests.begin();
while(reqiter!=_holt_requests.end())
{
HoltRequest* hreq = (*reqiter);
hreq->draw(ctx);
reqiter++;
}
}
void
HoltWidget::calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height)
{
cout << "Holt widget BEFORE calc_drawing_size width=" << width << " height=" << height << endl;
// int pos = _simulation->get_front();
// const History& hist = _simulation->get_history();
int max = _n_proc;
if(_n_res>_n_proc)
max = _n_res;
cairo_text_extents_t extents;
// std::cout << " x_unit: " << std::endl;
Glib::ustring val("Process 999 Resource 999");
cairo_text_extents(ctx, val.c_str(), &extents);
_radius = extents.width/4.0;
switch(_arrange_mode)
{
case arrange_horizontal:
width = max * 4 * _radius;
height = 10 * _radius;
break;
case arrange_vertical:
width = 10 * _radius;
height = max * 4 * _radius;
break;
case arrange_circular:
int tot = (_n_proc + _n_res);
double alpha = 0;
if(tot>0)
alpha = M_PI / tot;
double side = 2 * sin(alpha/2);
double diam = 4 * _radius;
if(side>0)
{
diam = 4 * _radius / side;
}
// double circ = 4 * _radius * (_n_proc + _n_res);
// double diam = circ / M_PI;
if(diam<4 * _radius)
diam = 4 * _radius;
width = height = diam + 4 * _radius;
break;
}
cout << "Holt widget AFTER calc_drawing_size width=" << width << " height=" << height << endl;
}
void
HoltWidget::calc_widget_size(size_t& width, size_t& height)
{
cout << "Holt widget BEFORE calc_widget_size width=" << width << " height=" << height << endl;
width = height = 20; // default minimum size
}