- 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 #define empty global variables
bin_PROGRAMS = bin_PROGRAMS =
mod_LTLIBRARIES =
mod_PYTHON = mod_PYTHON =
noinst_HEADERS = noinst_HEADERS =
pkglib_LTLIBRARIES = pkglib_LTLIBRARIES =
@ -136,7 +137,8 @@ src_backend_libbackend_la_CXXFLAGS = \
src_backend_libbackend_la_LDFLAGS = \ src_backend_libbackend_la_LDFLAGS = \
$(GLIBMM_LDFLAGS) \ $(GLIBMM_LDFLAGS) \
$(LT_LDFLAGS) \ $(LT_LDFLAGS) \
-version-info 0:0:0 -version-info 0:0:0 \
-export-dynamic
# Please keep this in sorted order: # Please keep this in sorted order:
src_backend_libbackend_la_SOURCES = \ 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 = \ src_backend_pyloader_libpyloader_la_CPPFLAGS = \
-I@top_srcdir@ \ -I@top_srcdir@ \
@ -247,12 +249,14 @@ src_backend_pyloader_libpyloader_la_LIBADD = \
src_backend_pyloader_libpyloader_la_LDFLAGS = \ src_backend_pyloader_libpyloader_la_LDFLAGS = \
$(PYTHON_EXTRA_LDFLAGS) \ $(PYTHON_EXTRA_LDFLAGS) \
$(LT_LDFLAGS) \ $(LT_LDFLAGS) \
-version-info 0:0:0 -version-info 0:0:0 \
-module
# Please keep this in sorted order: # Please keep this in sorted order:
src_backend_pyloader_libpyloader_la_SOURCES = \ src_backend_pyloader_libpyloader_la_SOURCES = \
src/backend/pyloader/python_policy.cc \ 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 += \ noinst_HEADERS += \
src/backend/pyloader/python_policy.hh \ src/backend/pyloader/python_policy.hh \
@ -272,7 +276,7 @@ mod_PYTHON += \
proxies = src/backend/pyloader/sgpem.py proxies = src/backend/pyloader/sgpem.py
wrappers = src/backend/pyloader/sgpem_wrap.cc wrappers = src/backend/pyloader/sgpem_wrap.cc
mod_LTLIBRARIES = _sgpem.la mod_LTLIBRARIES += _sgpem.la
mod_PYTHON += $(proxies) mod_PYTHON += $(proxies)
# static pattern rule # static pattern rule
@ -328,7 +332,6 @@ pyc_PYTHON = \
tests_PROGRAMS = src/testsuite/test-python_loader tests_PROGRAMS = src/testsuite/test-python_loader
# Shouldn't need Gtkmm! This is a coding anomaly
src_testsuite_test_python_loader_CPPFLAGS = \ src_testsuite_test_python_loader_CPPFLAGS = \
-I@top_srcdir@/src \ -I@top_srcdir@/src \
-DPYCDIR="\"$(pycdir)\"" \ -DPYCDIR="\"$(pycdir)\"" \
@ -336,8 +339,10 @@ src_testsuite_test_python_loader_CPPFLAGS = \
$(PYTHON_CPPFLAGS) \ $(PYTHON_CPPFLAGS) \
$(GLIBMM_CFLAGS) \ $(GLIBMM_CFLAGS) \
$(GTHREAD_CFLAGS) $(GTHREAD_CFLAGS)
src_testsuite_test_python_loader_DEPENDENCIES = \
src/backend/pyloader/libpyloader.la
src_testsuite_test_python_loader_LDFLAGS = \ src_testsuite_test_python_loader_LDFLAGS = \
src/backend/pyloader/libpyloader.la \ src/backend/libbackend.la \
$(GTKMM_LIBS) $(GTHREAD_LIBS) $(GTKMM_LIBS) $(GTHREAD_LIBS)
src_testsuite_test_python_loader_SOURCES = \ src_testsuite_test_python_loader_SOURCES = \
src/testsuite/test-python_loader.cc \ 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 "scheduler.hh"
#include "policy_parameters.hh" #include "policy_parameters.hh"
#include "user_interrupt_exception.hh"
namespace sgpem namespace sgpem
{ {
@ -51,7 +52,7 @@ namespace sgpem
Because it's a pure virtual method, must be re-implemented Because it's a pure virtual method, must be re-implemented
in concrete derived classes. 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 Sort the \ref SchedulableQueue object that contain all the Schedulable objects
@ -61,7 +62,7 @@ namespace sgpem
in concrete derived classes. in concrete derived classes.
\param event Call reason. Needed only by some scheduling policies. \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. Gets the unique identifier (id) of this Policy.
@ -88,7 +89,7 @@ namespace sgpem
in concrete derived classes. in concrete derived classes.
\return True if this policy is preemptible. \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. Gets the time quantum for the policy.
@ -97,16 +98,7 @@ namespace sgpem
in concrete derived classes. in concrete derived classes.
\return Time quantum for the policy. \return Time quantum for the policy.
*/ */
virtual int get_time_slice() const = 0; virtual int get_time_slice() const throw(UserInterruptException) = 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;
/** /**
Gets the parameters related with this policy. Gets the parameters related with this policy.

View File

@ -21,8 +21,23 @@
#include "policy_manager.hh" #include "policy_manager.hh"
PolicyManager*
PolicyManager::_registered = NULL;
PolicyManager::PolicyManager()
{
_registered = this;
}
PolicyManager::~PolicyManager() 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 class SG_DLLEXPORT PolicyManager
{ {
public: 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; virtual ~PolicyManager() = 0;
/** /**
@ -49,6 +60,16 @@ namespace sgpem
Init (or reset if yet initialized) the manager. Init (or reset if yet initialized) the manager.
*/ */
virtual void init() = 0; 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 } //~ 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 void
PythonPolicy::wait_unlock() const throw(UserInterruptException) PythonPolicy::wait_unlock() const throw(UserInterruptException)
{ {

View File

@ -76,12 +76,6 @@ namespace sgpem
*/ */
int get_time_slice() const throw(UserInterruptException); 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: private:
PythonPolicy(const char* name); PythonPolicy(const char* name);
PythonPolicy(const PythonPolicy&); PythonPolicy(const PythonPolicy&);

View File

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

View File

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

View File

@ -22,6 +22,8 @@
#define SCHEDULER_HH 1 #define SCHEDULER_HH 1
namespace sgpem namespace sgpem
{ {
class Scheduler;
class PolicyManager;
class Policy; class Policy;
} }
@ -71,9 +73,11 @@ namespace sgpem
event_end_time_slice event_end_time_slice
}; };
/** /** \brief Returns the unique instance of this class, conforming to the Singleton pattern.
Returns the unique instance of this class, conforming to the Singleton pattern. *
\return 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(); 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. 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. \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); void set_policy(Policy* policy);
*/
/** /**
Returns the policy that will be used to generate the simulation at the next instant. 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. \return the policy that will be used to generate the simulation at the next instant.
*/ */
Policy* get_policy(); Policy& get_policy();
private: private:
Scheduler(int); //private constructor. The parameter is discarded Scheduler(); //private constructor.
static Scheduler _instance; static Scheduler* _instance;
SchedulableList _ready_queue; SchedulableList _ready_queue;
Policy* _policy; PolicyManager& _policy_manager;
}; };
}//~ namespace sgpem }//~ namespace sgpem

View File

@ -39,8 +39,10 @@
#include "backend/dummy_policy.hh" #include "backend/dummy_policy.hh"
#include <glibmm/module.h>
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
#include <cassert>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
@ -60,6 +62,15 @@ main(int argc, char* argv[])
bindtextdomain(PACKAGE, LOCALEDIR); bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE); 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 // Set up Glib thread support
Glib::thread_init(); 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 // Create an INITIAL STATE
Process p1("P1", 0,5,1); Process p1("P1", 0,5,1);
Process p2("P2", 0,5,2); Process p2("P2", 0,5,2);
@ -108,6 +110,10 @@ main(int argc, char* argv[])
initial.add_at_bottom(ss6); initial.add_at_bottom(ss6);
History::get_instance().enqueue_slice(initial); 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 //the textual simulation
TextSimulation text_sim; TextSimulation text_sim;
History::get_instance().attach(&text_sim); History::get_instance().attach(&text_sim);
@ -194,5 +200,6 @@ main(int argc, char* argv[])
cout << "\n\n"; cout << "\n\n";
*/ */
return 0; return 0;
} }

View File

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

View File

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