- Make libpyloader a loadable plugin (warning: won't work

on Window$ unless you change the string "libpyloader" to
"pyloader" into main.cc)
- Fix Makefile to support module creation and loading
- 2DO: 
	- Add a class into backend to load and manage plugins
	- Install plugins into separate directory
	- Remove hardcoded paths


git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@458 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
tchernobog 2006-02-25 12:21:30 +00:00
parent 38f7b84909
commit 56534edb6c
15 changed files with 187 additions and 215 deletions

View File

@ -34,6 +34,7 @@ testsdir = $(pkgdatadir)/tests
#define empty global variables
bin_PROGRAMS =
mod_LTLIBRARIES =
mod_PYTHON =
noinst_HEADERS =
pkglib_LTLIBRARIES =
@ -136,7 +137,8 @@ src_backend_libbackend_la_CXXFLAGS = \
src_backend_libbackend_la_LDFLAGS = \
$(GLIBMM_LDFLAGS) \
$(LT_LDFLAGS) \
-version-info 0:0:0
-version-info 0:0:0 \
-export-dynamic
# Please keep this in sorted order:
src_backend_libbackend_la_SOURCES = \
@ -228,7 +230,7 @@ noinst_HEADERS += \
#
# ############################################################
pkglib_LTLIBRARIES += src/backend/pyloader/libpyloader.la
mod_LTLIBRARIES += src/backend/pyloader/libpyloader.la
src_backend_pyloader_libpyloader_la_CPPFLAGS = \
-I@top_srcdir@ \
@ -247,12 +249,14 @@ src_backend_pyloader_libpyloader_la_LIBADD = \
src_backend_pyloader_libpyloader_la_LDFLAGS = \
$(PYTHON_EXTRA_LDFLAGS) \
$(LT_LDFLAGS) \
-version-info 0:0:0
-version-info 0:0:0 \
-module
# Please keep this in sorted order:
src_backend_pyloader_libpyloader_la_SOURCES = \
src/backend/pyloader/python_policy.cc \
src/backend/pyloader/python_policy_manager.cc
src/backend/pyloader/python_policy_manager.cc \
src/backend/pyloader/hook.cc
noinst_HEADERS += \
src/backend/pyloader/python_policy.hh \
@ -272,7 +276,7 @@ mod_PYTHON += \
proxies = src/backend/pyloader/sgpem.py
wrappers = src/backend/pyloader/sgpem_wrap.cc
mod_LTLIBRARIES = _sgpem.la
mod_LTLIBRARIES += _sgpem.la
mod_PYTHON += $(proxies)
# static pattern rule
@ -328,7 +332,6 @@ pyc_PYTHON = \
tests_PROGRAMS = src/testsuite/test-python_loader
# Shouldn't need Gtkmm! This is a coding anomaly
src_testsuite_test_python_loader_CPPFLAGS = \
-I@top_srcdir@/src \
-DPYCDIR="\"$(pycdir)\"" \
@ -336,8 +339,10 @@ src_testsuite_test_python_loader_CPPFLAGS = \
$(PYTHON_CPPFLAGS) \
$(GLIBMM_CFLAGS) \
$(GTHREAD_CFLAGS)
src_testsuite_test_python_loader_DEPENDENCIES = \
src/backend/pyloader/libpyloader.la
src_testsuite_test_python_loader_LDFLAGS = \
src/backend/pyloader/libpyloader.la \
src/backend/libbackend.la \
$(GTKMM_LIBS) $(GTHREAD_LIBS)
src_testsuite_test_python_loader_SOURCES = \
src/testsuite/test-python_loader.cc \

View File

@ -1,71 +0,0 @@
// src/backend/dummy_policy.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 "dummy_policy.hh"
using namespace std;
using namespace sgpem;
DummyPolicy::~DummyPolicy()
{
}
void
DummyPolicy::configure()
{
_id = 100;
_parameters.clear();
_parameters.register_int("var1", 0, 10, true, 5);
_parameters.register_int("var2", -100, +100, false);
_parameters.register_float("kernel", 0, 10, true, 3.1415);
_parameters.register_float("multiplier", -100000, 100000, true, 1000);
_parameters.register_string("che_ne_so", true);
}
Glib::ustring
DummyPolicy::get_description() const
{
return "This is a dummy policy implemented in C++. It is just needed as a debug stub.";
}
bool
DummyPolicy::is_pre_emptive() const
{
return true;
}
int
DummyPolicy::get_time_slice() const
{
return _time_slice;
}
void
DummyPolicy::set_time_slice( const int& i)
{
_time_slice = i;
}
void
DummyPolicy::sort_queue(sgpem::Scheduler::event) const
{
return;
}

View File

@ -1,56 +0,0 @@
// src/backend/dummy_policy.hh - 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
#ifndef DUMMYPOLICY_HH
#define DUMMYPOLICY_HH 1
#include "config.h"
#include "glibmm/ustring.h"
#include "policy.hh"
namespace sgpem
{
class DummyPolicy;
/** \brief This is a trivial policy for demostration purposes only
*
* This trivial schedulation policy was needed during initial development
* as stub. It is now maintained as an example of how built-in policy can
* be implemented in C++.
*/
class SG_DLLEXPORT DummyPolicy : public Policy
{
public:
virtual ~DummyPolicy();
virtual void configure();
virtual void sort_queue(sgpem::Scheduler::event) const;
virtual Glib::ustring get_description() const;
virtual bool is_pre_emptive() const;
virtual int get_time_slice() const;
virtual void set_time_slice(const int&);
private:
int _time_slice;
};
} //~ namespace sgpem
#endif // DUMMYPOLICY_HH

View File

@ -28,6 +28,7 @@
#include "scheduler.hh"
#include "policy_parameters.hh"
#include "user_interrupt_exception.hh"
namespace sgpem
{
@ -51,7 +52,7 @@ namespace sgpem
Because it's a pure virtual method, must be re-implemented
in concrete derived classes.
*/
virtual void configure() = 0;
virtual void configure() throw(UserInterruptException) = 0;
/**
Sort the \ref SchedulableQueue object that contain all the Schedulable objects
@ -61,7 +62,7 @@ namespace sgpem
in concrete derived classes.
\param event Call reason. Needed only by some scheduling policies.
*/
virtual void sort_queue(Scheduler::event event) const = 0;
virtual void sort_queue(Scheduler::event event) const throw(UserInterruptException) = 0;
/**
Gets the unique identifier (id) of this Policy.
@ -88,7 +89,7 @@ namespace sgpem
in concrete derived classes.
\return True if this policy is preemptible.
*/
virtual bool is_pre_emptive() const = 0;
virtual bool is_pre_emptive() const throw(UserInterruptException) = 0;
/**
Gets the time quantum for the policy.
@ -97,16 +98,7 @@ namespace sgpem
in concrete derived classes.
\return Time quantum for the policy.
*/
virtual int get_time_slice() const = 0;
/**
Sets the time quantum for the policy.
Because it's a pure virtual method, must be re-implemented
in concrete derived classes.
\param quantum The desired time quantum for the policy.
*/
virtual void set_time_slice(const int& quantum) = 0;
virtual int get_time_slice() const throw(UserInterruptException) = 0;
/**
Gets the parameters related with this policy.

View File

@ -21,8 +21,23 @@
#include "policy_manager.hh"
PolicyManager*
PolicyManager::_registered = NULL;
PolicyManager::PolicyManager()
{
_registered = this;
}
PolicyManager::~PolicyManager()
{
// This check is necessary:
if(_registered == this) _registered = NULL;
}
PolicyManager&
PolicyManager::get_registered_manager()
{
return *_registered;
}

View File

@ -36,6 +36,17 @@ namespace sgpem
class SG_DLLEXPORT PolicyManager
{
public:
/** \brief PolicyManager 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 PolicyManager can be saved. This will
* be expanded in next milestones.
*/
PolicyManager();
virtual ~PolicyManager() = 0;
/**
@ -49,6 +60,16 @@ namespace sgpem
Init (or reset if yet initialized) the manager.
*/
virtual void init() = 0;
/** \brief Get the registered manager instance
*
* \return The registered policy manager instance.
*/
static PolicyManager& get_registered_manager();
private:
/** A pointer to the registered instance */
static PolicyManager* _registered;
};
} //~ namespace sgpem

View File

@ -0,0 +1,54 @@
// src/backend/pyloader/hook.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
// The idea of this file is to provide a static function to execute
// when the plugin (this library) is loaded. Thus the name "hook".
// For the moment, instead of a function hook to be called by the
// libbackend.so module, we have a static PythonPolicyManager object.
// This is a risk.
#warning FIXME : this code is quite a bad idea. Replace me with \
a hookable structure, and execute a pointer to function stored \
therein. See "info libtool": "dlopened modules"
#include "python_policy_manager.hh"
#ifdef __cplusplus
extern "C" {
#endif
#define SG_CONSTRUCTOR __attribute__ ((constructor))
#define SG_DESTRUCTOR __attribute__ ((destructor))
PolicyManager* _global_pm = NULL;
void SG_DLLEXPORT SG_CONSTRUCTOR hook_ctor(void)
{
_global_pm = PythonPolicyManager::get_instance();
}
void SG_DLLEXPORT SG_DESTRUCTOR hook_dtor(void)
{
delete _global_pm;
}
#ifdef __cplusplus
}
#endif

View File

@ -153,13 +153,6 @@ PythonPolicy::get_time_slice() const throw(UserInterruptException) {
}
void
PythonPolicy::set_time_slice(const int&)
{
throw "The design is wrong, and I shouldn't be called.";
}
void
PythonPolicy::wait_unlock() const throw(UserInterruptException)
{

View File

@ -76,12 +76,6 @@ namespace sgpem
*/
int get_time_slice() const throw(UserInterruptException);
// Singing with Caipha's voice: "must die, must die, this method must die!"
/**
Changes the time-slice of the policy.
*/
void set_time_slice(const int&);
private:
PythonPolicy(const char* name);
PythonPolicy(const PythonPolicy&);

View File

@ -185,7 +185,7 @@ namespace sgpem {
// ---------------------------------------------
class Scheduler {
public:
sgpem::Policy* get_policy();
sgpem::Policy& get_policy();
static sgpem::Scheduler& get_instance();
sgpem::SchedulableList* get_ready_queue();
private:

View File

@ -20,23 +20,27 @@
#include "policy.hh"
#include "scheduler.hh"
#include "policy_manager.hh"
using namespace std;
using namespace sgpem;
using namespace memory;
//static object
Scheduler Scheduler::_instance(10); //dummy parameter
Scheduler*
Scheduler::_instance = 0;
/**
*/
Scheduler::Scheduler(int) //private constructor. The parameter is discarded
{}
//private constructor. The parameter is discarded
Scheduler::Scheduler()
: _policy_manager(PolicyManager::get_registered_manager())
{
_policy_manager.init();
}
Scheduler&
Scheduler::get_instance()
{
return _instance;
if(!_instance)
_instance = new Scheduler();
return *_instance;
}
SchedulableList*
@ -58,23 +62,24 @@ Scheduler::reset_status()
// restore the policy
}
void
/* void
Scheduler::set_policy(Policy* p)
{
_policy = p;
}
_policy_manager.set_policy(p);
}*/
Policy*
Policy&
Scheduler::get_policy()
{
return _policy;
return _policy_manager.get_policy();
}
void
Scheduler::step_forward()
{
Policy& policy = get_policy();
History& h = History::get_instance();
//******************
@ -107,7 +112,7 @@ Scheduler::step_forward()
//cout << "\nnuovo running: " << initial->get_item_at(i)->get_schedulable()->get_name();
//restore the old running schedulable
if (_policy->is_pre_emptive() == false && running_ptr)
if (policy.is_pre_emptive() == false && running_ptr)
_ready_queue.remove(0);
//adds the NEW one
@ -116,10 +121,10 @@ Scheduler::step_forward()
initial->get_item_at(i)->set_state(SchedulableStatus::state_ready);
// Sort the queue
_policy->sort_queue(event_schedulable_arrival);
policy.sort_queue(event_schedulable_arrival);
//restore the old running schedulable
if (_policy->is_pre_emptive() == false && running_ptr)
if (policy.is_pre_emptive() == false && running_ptr)
_ready_queue.add_at_top(*running_ptr);
}
@ -143,14 +148,14 @@ Scheduler::step_forward()
running_ptr = NULL;
//IF _ready_queue.size() == 0 sort_queue(...) is called but has no effect!!
_policy->sort_queue(event_schedulable_termination);
policy.sort_queue(event_schedulable_termination);
}
//*****************
// Check for time slice
//*****************
if (_policy->get_time_slice() != numeric_limits<int>::max()) //time-slice
_policy->sort_queue(event_end_time_slice);
if (policy.get_time_slice() != numeric_limits<int>::max()) //time-slice
policy.sort_queue(event_end_time_slice);
//******************
// Create the final list of schedulable

View File

@ -22,6 +22,8 @@
#define SCHEDULER_HH 1
namespace sgpem
{
class Scheduler;
class PolicyManager;
class Policy;
}
@ -71,9 +73,11 @@ namespace sgpem
event_end_time_slice
};
/**
Returns the unique instance of this class, conforming to the Singleton pattern.
\return the unique instance of this class, conforming to the Singleton pattern.
/** \brief Returns the unique instance of this class, conforming to the Singleton pattern.
*
* If Scheduler isn't initialized, creates it. Should be called at least once before
* starting the Simulation.
* \return the unique instance of this class, conforming to the Singleton pattern.
*/
static Scheduler& get_instance();
/**
@ -97,19 +101,21 @@ namespace sgpem
Sets the policy that will be used to generate the simulation at the next instant.
\param policy the policy that will be used to generate the simulation at the next instant.
*/
/* DISABLED until we don't have PolicyManager::set_policy()
void set_policy(Policy* policy);
*/
/**
Returns the policy that will be used to generate the simulation at the next instant.
\return the policy that will be used to generate the simulation at the next instant.
*/
Policy* get_policy();
Policy& get_policy();
private:
Scheduler(int); //private constructor. The parameter is discarded
static Scheduler _instance;
Scheduler(); //private constructor.
static Scheduler* _instance;
SchedulableList _ready_queue;
Policy* _policy;
PolicyManager& _policy_manager;
};
}//~ namespace sgpem

View File

@ -39,8 +39,10 @@
#include "backend/dummy_policy.hh"
#include <glibmm/module.h>
#include <glibmm/ustring.h>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
@ -60,6 +62,15 @@ main(int argc, char* argv[])
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
// FIXME: this will need to be moved to an
// appropriate PluginManager class in the backend,
// and the Makefile fixed accordingly
using Glib::Module;
std::string pyloader_path = Module::build_path(MODDIR, "pyloader");
Module pyloader(pyloader_path);
std::cerr << Module::get_last_error() << std::endl;
assert(pyloader);
// Set up Glib thread support
Glib::thread_init();
@ -75,15 +86,6 @@ main(int argc, char* argv[])
}
*/
// Set the unique POLICY
DummyPolicy pol;
pol.configure();
pol.get_parameters().set_int("var2", 33);
pol.get_parameters().set_float("multiplier", 100);
pol.get_parameters().set_string("che_ne_so", "ciao");
Scheduler::get_instance().set_policy(&pol);
// Create an INITIAL STATE
Process p1("P1", 0,5,1);
Process p2("P2", 0,5,2);
@ -108,6 +110,10 @@ main(int argc, char* argv[])
initial.add_at_bottom(ss6);
History::get_instance().enqueue_slice(initial);
Scheduler::get_instance(); // Forces initialization of scheduler.
// Cross fingers (depends if PythonPolicyManager
// static object has been initialized before?).
//the textual simulation
TextSimulation text_sim;
History::get_instance().attach(&text_sim);
@ -194,5 +200,6 @@ main(int argc, char* argv[])
cout << "\n\n";
*/
return 0;
}

View File

@ -159,23 +159,23 @@ Simulation::jump_to(const uint& where)
_mode = old;
}
void
/*void
Simulation::set_policy(Policy* p)
{
Scheduler::get_instance().set_policy(p);
}
}*/
Policy*
Simulation::get_policy()
{
return Scheduler::get_instance().get_policy();
return &Scheduler::get_instance().get_policy();
}
vector<Policy*>
Simulation::get_avaiable_policies()
{
vector<Policy*> v;
v.push_back(Scheduler::get_instance().get_policy());
v.push_back(&Scheduler::get_instance().get_policy());
return v;
}

View File

@ -31,11 +31,19 @@
#include "text_simulation.hh"
#include "templates/smartp.hh"
#include <glibmm/module.h>
#include <cassert>
#include <string>
int
main(int argc, char** argv) {
using namespace sgpem;
using Glib::Module;
std::string pyloader_path = Module::build_path(MODDIR, "pyloader");
Glib::Module pyloader(pyloader_path);
assert(pyloader);
Glib::thread_init();
@ -63,10 +71,9 @@ main(int argc, char** argv) {
initial.add_at_bottom(ss6);
History::get_instance().enqueue_slice(initial);
PythonPolicyManager* ppm = PythonPolicyManager::get_instance();
ppm->init();
Policy& pol = ppm->get_policy();
Scheduler::get_instance().set_policy(&pol);
Scheduler::get_instance(); // Forces initialization of scheduler.
// Cross fingers (depends if PythonPolicyManager
// static object has been initialized before?).
//the textual simulation
TextSimulation text_sim;