938 lines
23 KiB
C++
938 lines
23 KiB
C++
// src/holt_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 <sgpemv2/history.hh>
|
|
#include <sgpemv2/schedulable.hh>
|
|
#include <sgpemv2/resource.hh>
|
|
#include <sgpemv2/simulation.hh>
|
|
#include <sgpemv2/string_utils.hh>
|
|
#include <sgpemv2/thread.hh>
|
|
|
|
#include "holt_widget.hh"
|
|
|
|
#include <sgpemv2/templates/deletor.tcc>
|
|
#include <sgpemv2/templates/sequences.tcc>
|
|
|
|
#include <math.h>
|
|
|
|
#include <cassert>
|
|
|
|
#ifndef NDEBUG
|
|
#include <iostream>
|
|
#endif
|
|
|
|
#include <sstream>
|
|
|
|
using namespace sgpem;
|
|
using namespace std;
|
|
|
|
#ifndef M_SQRT1_2
|
|
#define M_SQRT1_2 0.70710678118654752440
|
|
#endif
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
|
|
HoltNode::HoltNode(Vec2 pt)
|
|
: _radius(20)
|
|
{
|
|
_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;
|
|
}
|
|
|
|
|
|
HoltResource::HoltResource(const Resource& resource, resource_key_t resource_key, Vec2 pt)
|
|
: HoltNode(pt),
|
|
_resource(&resource),
|
|
_resource_key(resource_key),
|
|
_used_places(0)
|
|
{
|
|
}
|
|
|
|
HoltResource::~HoltResource()
|
|
{
|
|
}
|
|
|
|
void HoltResource::draw(cairo_t *cr)
|
|
{
|
|
static const Color white(1, 1, 1);
|
|
|
|
static const float x_percent = 3.5f / 4;
|
|
static const float y_percent = 4.5f / 5;
|
|
|
|
CairoElements ce(cr);
|
|
|
|
// outline
|
|
cairo_set_source_rgb (cr, 0, 0, 0);
|
|
|
|
// draw rectangle
|
|
Rectangle area(_pos.real() - _radius, _pos.imag() - _radius, 2*_radius, 2*_radius);
|
|
ce.draw_3dcube(area, white, x_percent, y_percent);
|
|
|
|
cairo_save(cr);
|
|
// clip text outside region
|
|
/*
|
|
cairo_rectangle(cr,
|
|
_pos.real() - _radius,
|
|
_pos.imag() - _radius, // _pos.imag() + _radius (1 - 2.0 * y_percent)
|
|
2 * _radius * x_percent,
|
|
2 * _radius * y_percent);
|
|
*/
|
|
|
|
cairo_rectangle(cr,
|
|
_pos.real() - _radius,
|
|
_pos.imag() + _radius * (1 - 2.0 * y_percent),
|
|
2 * _radius * x_percent,
|
|
2 * _radius * y_percent);
|
|
|
|
cairo_clip(cr);
|
|
// draw text
|
|
cairo_text_extents_t extents;
|
|
cairo_text_extents(cr, _resource->get_name().c_str(), &extents);
|
|
double xpos = _pos.real() + _radius * (x_percent-1) - extents.width/2.0;
|
|
double ypos = _pos.imag() + _radius * (1 - y_percent); // + extents.height/2;
|
|
// _pos.imag() + extents.height * ((1 - y_percent) / 2 + 0.5)
|
|
|
|
// left aligned if too large
|
|
if(xpos<_pos.real() - _radius)
|
|
xpos = _pos.real() - _radius;
|
|
cairo_move_to(cr,
|
|
xpos,
|
|
ypos );
|
|
cairo_show_text(cr, _resource->get_name().c_str());
|
|
|
|
// show used/total places
|
|
Glib::ustring used;
|
|
to_string<int>((int)_used_places, used);
|
|
Glib::ustring total;
|
|
to_string<int>((int)_resource->get_places(), total);
|
|
|
|
Glib::ustring msg = used + "/" + total;
|
|
cairo_text_extents(cr, msg.c_str(), &extents);
|
|
xpos = _pos.real() + _radius * (x_percent-1) - extents.width/2.0;
|
|
ypos = _pos.imag() + _radius * (1 - y_percent) + extents.height*2;
|
|
cairo_move_to(cr,
|
|
xpos,
|
|
ypos );
|
|
cairo_show_text(cr, msg.c_str());
|
|
|
|
// stroke all
|
|
cairo_stroke (cr);
|
|
|
|
cairo_restore(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;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
HoltResource::allocate(unsigned int places)
|
|
{
|
|
_used_places += places;
|
|
}
|
|
|
|
unsigned int
|
|
HoltResource::get_allocated()
|
|
{
|
|
return _used_places;
|
|
}
|
|
|
|
|
|
|
|
|
|
HoltSchedulable::HoltSchedulable(const Schedulable& schedulable, Vec2 pt)
|
|
: HoltNode(pt)
|
|
{
|
|
_schedulable = &schedulable;
|
|
}
|
|
|
|
HoltSchedulable::~HoltSchedulable()
|
|
{
|
|
}
|
|
|
|
void HoltSchedulable::draw(cairo_t *cr)
|
|
{
|
|
static const Color red(1, 0, 0);
|
|
static const Color yellow(1, 0.8, 0);
|
|
static const Color green(0, 1, 0);
|
|
|
|
|
|
cairo_save(cr); // save context state
|
|
|
|
const Point center(_pos.real(), _pos.imag());
|
|
const Color* color = &red;
|
|
|
|
// draw circle
|
|
CairoElements cel(cr);
|
|
// filling
|
|
switch(_schedulable->get_state())
|
|
{
|
|
case Schedulable::state_running:
|
|
color = &green;
|
|
break;
|
|
case Schedulable::state_ready:
|
|
color = &yellow;
|
|
break;
|
|
case Schedulable::state_blocked:
|
|
color = &red;
|
|
break;
|
|
case Schedulable::state_future:
|
|
case Schedulable::state_terminated:
|
|
// should never get here
|
|
assert((_schedulable->get_state() & (Schedulable::state_future | Schedulable::state_terminated)) == 0);
|
|
}
|
|
|
|
cel.draw_3dsphere(center, _radius, *color);
|
|
|
|
// clip text outside region
|
|
cairo_arc(cr, _pos.real(), _pos.imag(), _radius, 0, 2*M_PI);
|
|
cairo_clip(cr);
|
|
|
|
// draw text
|
|
cairo_text_extents_t extents;
|
|
cairo_text_extents(cr, _schedulable->get_name().c_str(), &extents);
|
|
double text_width = extents.width;
|
|
if(text_width>_radius*2.0)
|
|
text_width=_radius*2.0;
|
|
cairo_move_to(cr, _pos.real() - text_width/2, _pos.imag() + extents.height/2);
|
|
cairo_show_text(cr, _schedulable->get_name().c_str());
|
|
|
|
// stroke all
|
|
cairo_stroke (cr);
|
|
|
|
cairo_restore(cr); // restore context state
|
|
}
|
|
|
|
Vec2 HoltSchedulable::get_intersection_to(Vec2 pt)
|
|
{
|
|
// schedulables ar circles
|
|
// intersection is a radius from center then...
|
|
Vec2 final = _pos;
|
|
|
|
// take segment
|
|
Vec2 segment = pt - _pos;
|
|
double len = std::abs(segment);
|
|
|
|
// and normalize to radius
|
|
if(len>0)
|
|
{
|
|
segment *= _radius/len;
|
|
final = _pos + segment;
|
|
}
|
|
return final;
|
|
}
|
|
|
|
|
|
|
|
HoltRequest::HoltRequest(HoltSchedulable& hp, HoltResource& hr, Request::state state, unsigned int places)
|
|
: _hp(&hp),
|
|
_hr(&hr),
|
|
_state(state)
|
|
{
|
|
hr.allocate(places);
|
|
}
|
|
|
|
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);
|
|
|
|
switch(_state)
|
|
{
|
|
case Request::state_unallocable:
|
|
// red
|
|
cairo_set_source_rgb(cr, 1, 0, 0);
|
|
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, 0.7, 0);
|
|
arrow(cr, schedulable, resource);
|
|
break;
|
|
}
|
|
|
|
// stroke all and restore status
|
|
cairo_stroke (cr);
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
void HoltRequest::arrow(cairo_t *cr, Vec2 first, Vec2 second)
|
|
{
|
|
// option to draw the line a little translated
|
|
// this allow to draw two counterflow arrows
|
|
// without overlap
|
|
bool traslate = true;
|
|
double line_width = cairo_get_line_width(cr);
|
|
if(traslate)
|
|
{
|
|
// if needed calc parallel versor of arrow
|
|
Vec2 direction = second-first;
|
|
direction /= std::abs(direction); // set unary modulus
|
|
|
|
// and rotate it 90 degrees
|
|
Vec2 dir_rotation(0.0, 1.0);
|
|
direction *= dir_rotation;
|
|
|
|
// translation modulus equals line width
|
|
direction *= line_width;
|
|
first += direction;
|
|
second += direction;
|
|
}
|
|
|
|
// draw main line
|
|
cairo_move_to(cr, second.real(), second.imag());
|
|
cairo_line_to(cr, first.real(), first.imag());
|
|
|
|
// some calculation to draw arrowpoint...
|
|
// take a short line parallel to main line
|
|
Vec2 arrowside = second-first;
|
|
arrowside *= 5.0*line_width/std::abs(arrowside);
|
|
// make a rotation component
|
|
Vec2 deviation(5.0, 1.0); deviation /= std::abs(deviation);
|
|
// make left and right sides rotating that first short line
|
|
Vec2 side1 = arrowside * deviation;
|
|
Vec2 side2 = arrowside * conj(deviation);
|
|
// draw one side
|
|
cairo_move_to(cr, first.real(), first.imag());
|
|
cairo_line_to(cr, first.real()+side1.real(), first.imag()+side1.imag());
|
|
// draw the other side
|
|
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"),
|
|
SimulationObserver(),
|
|
HistoryObserver(),
|
|
CairoWidget(),
|
|
_simulation(&simulation),
|
|
_radius(20),
|
|
_n_proc(0),
|
|
_n_res(0),
|
|
_arrange_mode(arrange_horizontal),
|
|
_show_threads(false)
|
|
|
|
{
|
|
// Register this SimulationObserver:
|
|
_simulation->attach(*this);
|
|
|
|
// Register this HistoryObserver:
|
|
_simulation->get_history().attach(*this);
|
|
}
|
|
|
|
|
|
HoltWidget::~HoltWidget()
|
|
{
|
|
// Free allocated memory
|
|
const HoltResources& const_holt_resources = _holt_resources;
|
|
for(Iseq<HoltResources::const_iterator> it = iseq(const_holt_resources); it; ++it)
|
|
delete it->second;
|
|
|
|
for_each_in(_holt_schedulables, memory::deletor<HoltSchedulable>());
|
|
for_each_in(_holt_requests, memory::deletor<HoltRequest>());
|
|
|
|
|
|
// 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;
|
|
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();
|
|
return old_mode;
|
|
}
|
|
|
|
void
|
|
HoltWidget::arrange()
|
|
{
|
|
#ifndef NDEBUG
|
|
std::cout << "HoltWidget::arrange" << endl;
|
|
#endif
|
|
|
|
// Differents graph's dispositions are made easy by
|
|
// usual complex number algebra:
|
|
//
|
|
// v1 += v2 - translation
|
|
// v1 *= d - scaling
|
|
// v1 *= v2 - rotating if abs(v2)==1.0
|
|
// v1 *= v2 - rotating and scaling by modulus if abs(v2)!=1.0
|
|
//
|
|
// where v1, v2 are Vec2 (complex<double>), d is double
|
|
//
|
|
|
|
// to draw a linear disposition the algorithm starts with
|
|
// first desired position and sums an inc vetor each step
|
|
//
|
|
// to draw a circular disposition the center and radius are taken
|
|
// then every position is calculated summing to center a radius (inc)
|
|
// vector. The inc vector is rotated each step
|
|
//
|
|
|
|
Vec2 pos; // position of current HoltNode derived object (all)
|
|
Vec2 inc; // increment (vertical and horizontal) or radius (circular)
|
|
Vec2 cen; // center of rotation (circular only)
|
|
Vec2 mul; // rotation multiplier (circular only)
|
|
|
|
// vectors building
|
|
if(_arrange_mode==arrange_horizontal)
|
|
{
|
|
// first position
|
|
pos = Vec2(2*_radius, 2*_radius);
|
|
// increment
|
|
inc = Vec2(3*_radius, 0);
|
|
}
|
|
else if(_arrange_mode==arrange_vertical)
|
|
{
|
|
// first position
|
|
pos = Vec2(2*_radius, 2*_radius);
|
|
// increment
|
|
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();
|
|
// take minimum between x and y
|
|
/*
|
|
if(sx<=sy)
|
|
inc = Vec2((sx/2-2*_radius), 0);
|
|
else
|
|
inc = Vec2((sy/2-2*_radius), 0);
|
|
*/
|
|
if(nelem>1)
|
|
{
|
|
// take minimum between x and y
|
|
if(sx<=sy)
|
|
inc = Vec2(-(sx/2-2*_radius), 0);
|
|
else
|
|
inc = Vec2(-(sy/2-2*_radius), 0);
|
|
}
|
|
else
|
|
{
|
|
// zero or one object always at center
|
|
inc = Vec2(0, 0);
|
|
}
|
|
|
|
|
|
// calc rotation angle
|
|
if(nelem>0)
|
|
mul = Vec2(cos(2*M_PI/(double)nelem), sin(2*M_PI/(double)nelem));
|
|
else
|
|
mul = Vec2(0,0);
|
|
|
|
cen = Vec2(2*_radius+std::abs(inc), 2*_radius+std::abs(inc));
|
|
// cen = Vec2(sx/2.0, sy/2.0);
|
|
pos = inc + cen;
|
|
}
|
|
|
|
// positions all resources
|
|
HoltResources::const_iterator riter = _holt_resources.begin();
|
|
while(riter!=_holt_resources.end())
|
|
{
|
|
HoltResource* hr = (*riter).second;
|
|
hr->set_position(pos);
|
|
hr->set_radius(_radius);
|
|
|
|
// calc next position
|
|
if(_arrange_mode!=arrange_circular)
|
|
{
|
|
pos += inc;
|
|
}
|
|
else // _arrange_mode==arrange_circular
|
|
{
|
|
inc *= mul;
|
|
pos = cen + inc;
|
|
}
|
|
riter++;
|
|
}
|
|
|
|
// positions all schedulables
|
|
// if linear disposition then must reevaluate start and increment
|
|
// when circular continue with previous values to end circle
|
|
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);
|
|
hp->set_position(pos);
|
|
hp->set_radius(_radius);
|
|
|
|
if(_arrange_mode!=arrange_circular)
|
|
{
|
|
pos += inc;
|
|
}
|
|
else // _arrange_mode==arrange_circular
|
|
{
|
|
inc *= mul;
|
|
pos = cen + inc;
|
|
}
|
|
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*/)
|
|
{
|
|
}
|
|
|
|
|
|
void
|
|
HoltWidget::update(const History& /*changed_history*/)
|
|
{
|
|
#ifndef NDEBUG
|
|
std::cout << "HoltWidget::update - History" << endl;
|
|
#endif
|
|
// take new data
|
|
acquire();
|
|
|
|
// Force redraw
|
|
resize_redraw();
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
HoltWidget::acquire()
|
|
{
|
|
#ifndef NDEBUG
|
|
std::cout << "HoltWidget::acquire" << endl;
|
|
#endif
|
|
|
|
// clear all previous collected items
|
|
const HoltResources& const_holt_resources = _holt_resources;
|
|
for(Iseq<HoltResources::const_iterator> it = iseq(const_holt_resources); it; ++it)
|
|
delete it->second;
|
|
_holt_resources.clear();
|
|
|
|
for_each_in(_holt_schedulables, memory::deletor<HoltSchedulable>());
|
|
_holt_schedulables.clear();
|
|
|
|
for_each_in(_holt_requests, memory::deletor<HoltRequest>());
|
|
_holt_requests.clear();
|
|
|
|
_n_res = _n_proc = 0;
|
|
|
|
const History& hist = _simulation->get_history();
|
|
const Environment& env = hist.get_last_environment();
|
|
|
|
// arbitrary position (will be changed by arrange())
|
|
Vec2 pos(2*_radius, 2*_radius);
|
|
const Environment::Resources& rvect = env.get_resources();
|
|
|
|
// scan all resources making an HolResource object
|
|
Environment::Resources::const_iterator riter = rvect.begin();
|
|
while(riter!=rvect.end())
|
|
{
|
|
resource_key_t index = (*riter).first;
|
|
Resource* r = (*riter).second;
|
|
|
|
// create HolResource object and insert it in container
|
|
HoltResource *hr = new HoltResource(*r, index, pos);
|
|
HoltResources::iterator temp = _holt_resources.insert(std::pair<resource_key_t,HoltResource*>(index, hr)).first;
|
|
|
|
// count resources
|
|
_n_res++;
|
|
|
|
// skip to next
|
|
riter++;
|
|
|
|
// calc next position
|
|
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++;
|
|
|
|
// create a new HoltScedulable per process
|
|
// if running or ready or blocked and
|
|
// show threads is disabled
|
|
Schedulable::state proc_state = p->get_state();
|
|
if(proc_state==Schedulable::state_running
|
|
|| proc_state==Schedulable::state_ready
|
|
|| proc_state==Schedulable::state_blocked )
|
|
{
|
|
HoltSchedulable *hp;
|
|
if(!_show_threads)
|
|
{
|
|
hp = new HoltSchedulable(*p, pos);
|
|
_holt_schedulables.push_back(hp);
|
|
pos += Vec2(4*_radius, 0);
|
|
_n_proc++;
|
|
}
|
|
|
|
// iter trough threads, requests, subrequests
|
|
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++;
|
|
|
|
// create a new HoltScedulable per process
|
|
// if running or ready or blocked and
|
|
// show threads is disabled
|
|
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);
|
|
_n_proc++;
|
|
}
|
|
// 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++;
|
|
|
|
// create a new HoltRequest per subrequest
|
|
// if unallocable or allocated or allocable
|
|
// tieing it with current process or thread
|
|
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)
|
|
unsigned int nplaces = 0;
|
|
if(sr->get_state()==Request::state_allocated)
|
|
nplaces++;
|
|
HoltRequest *hreq = new HoltRequest(*hp, *(hpos->second), sr->get_state(), nplaces);
|
|
_holt_requests.push_back(hreq);
|
|
}
|
|
} // ~ if(subr_state==Request::state_unallocable ... etc
|
|
} // ~ 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
HoltWidget::draw_widget(cairo_t* ctx)
|
|
{
|
|
#ifndef NDEBUG
|
|
std::cout << "HoltWidget::draw_widget" << endl;
|
|
#endif
|
|
|
|
// dispose objects
|
|
arrange();
|
|
|
|
// draw text: T = n as title
|
|
if(_draw_w>0)
|
|
{
|
|
const History& hist = _simulation->get_history();
|
|
const unsigned int hist_front = hist.get_front() == 0 ? 0 : hist.get_front() - 1;
|
|
cairo_text_extents_t extents;
|
|
stringstream ss;
|
|
ss << "T = " << hist_front;
|
|
cairo_text_extents(ctx, ss.str().c_str(), &extents);
|
|
cairo_move_to(ctx, _draw_w/2 - extents.width/2.0, extents.height*2.0);
|
|
cairo_show_text(ctx, ss.str().c_str());
|
|
cairo_stroke(ctx);
|
|
}
|
|
|
|
|
|
|
|
// draw all resources
|
|
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++;
|
|
}
|
|
|
|
// draw all schedulables
|
|
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++;
|
|
}
|
|
|
|
// draw all arrows
|
|
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)
|
|
{
|
|
#ifndef DNDEBUG
|
|
cout << "Holt widget BEFORE calc_drawing_size width=" << width << " height=" << height << endl;
|
|
#endif
|
|
|
|
// the disposition of objects take care that:
|
|
// - an object has a 2.0*_radius diameter
|
|
// - a space _radius wide is required around objects
|
|
//
|
|
// this is the reason because the expression 4 * _radius
|
|
// recurs many times in the code below
|
|
//
|
|
int max = _n_proc;
|
|
if(_n_res>_n_proc)
|
|
max = _n_res;
|
|
cairo_text_extents_t extents;
|
|
|
|
static const 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:
|
|
// max number of items times the space required by one
|
|
width = (size_t) (max * 4 * _radius);
|
|
// aspace of 4 * _radius between rows
|
|
height = (size_t) (10 * _radius);
|
|
break;
|
|
|
|
case arrange_vertical:
|
|
// aspace of 4 * _radius between columns
|
|
width = (size_t) (10 * _radius);
|
|
// max number of items times the space required by one
|
|
height = (size_t) (max * 4 * _radius);
|
|
break;
|
|
|
|
case arrange_circular:
|
|
// lilltle more complex diameter calculation
|
|
// the circle is divided in tot sectors
|
|
int tot = (_n_proc + _n_res);
|
|
// each sector is alpha wide
|
|
double alpha = 0;
|
|
if(tot>0)
|
|
alpha = M_PI / tot;
|
|
// each element is placed on vertex of a tot sides polygon
|
|
// side length
|
|
double side = 2 * sin(alpha/2);
|
|
// calc of expected limiting circle diameter
|
|
double diam = 4 * _radius;
|
|
if(side>0)
|
|
{
|
|
diam = 4 * _radius / side;
|
|
}
|
|
if(diam<4 * _radius)
|
|
diam = 4 * _radius;
|
|
width = height = (size_t) (diam + 4 * _radius);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
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
|
|
}
|
|
*/
|