- Merged branch 0.3-r556--SPLIT_PYLOADER_CONFIG back into trunk
git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@561 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
c6d4f5fd27
commit
51f0d7fbe7
36 changed files with 849 additions and 48 deletions
|
@ -1,96 +0,0 @@
|
|||
## @brief Defines a class to create abstract methods
|
||||
#
|
||||
# @author Ivo Timmermans
|
||||
# @date 2004/01/23
|
||||
# @version 1.1
|
||||
#
|
||||
# Example:
|
||||
# @code
|
||||
# import Abstract;
|
||||
# class Foo:
|
||||
# __metaclass__ = Abstract.Metaclass
|
||||
# foo = Abstract.AbstractMethod('foo')
|
||||
# @endcode
|
||||
class AbstractMethod (object):
|
||||
## @brief Constructor
|
||||
#
|
||||
# @param func name of the function (used when raising an
|
||||
# exception). Its type is str.
|
||||
def __init__(self, func):
|
||||
self._function = func
|
||||
|
||||
## @brief Get callable object
|
||||
#
|
||||
# @return An instance of AbstractMethodHelper.
|
||||
# This trickery is needed to get the name of the class for which
|
||||
# an abstract method was requested, otherwise it would be
|
||||
# sufficient to include a __call__ method in the AbstractMethod
|
||||
# class itself.
|
||||
def __get__(self, obj, type):
|
||||
return self.AbstractMethodHelper(self._function, type)
|
||||
|
||||
## @brief Abstract method helper class
|
||||
#
|
||||
# An AbstractMethodHelper instance is a callable object that
|
||||
# represents an abstract method.
|
||||
class AbstractMethodHelper (object):
|
||||
def __init__(self, func, cls):
|
||||
self._function = func
|
||||
self._class = cls
|
||||
|
||||
## @brief Call abstract method
|
||||
#
|
||||
# Raises a TypeError, because abstract methods can not be
|
||||
# called.
|
||||
def __call__(self, *args, **kwargs):
|
||||
raise TypeError('Abstract method `' + self._class.__name__ \
|
||||
+ '.' + self._function + '\' called')
|
||||
|
||||
## @brief Configure a new class to be abstract
|
||||
#
|
||||
# @author Ivo Timmermans
|
||||
# @date 2004/01/23
|
||||
# @version 1.1
|
||||
class Metaclass (type):
|
||||
## Configure a new class
|
||||
#
|
||||
# @param cls Class object
|
||||
# @param name Name of the class
|
||||
# @param bases All base classes for cls
|
||||
def __init__(cls, name, bases, *args, **kwargs):
|
||||
super(Metaclass, cls).__init__(cls, name, bases, *args, **kwargs)
|
||||
|
||||
# Detach cls.new() from class Metaclass, and make it a method
|
||||
# of cls.
|
||||
cls.__new__ = staticmethod(cls.new)
|
||||
|
||||
# Find all abstract methods, and assign the resulting list to
|
||||
# cls.__abstractmethods__, so we can read that variable when a
|
||||
# request for allocation (__new__) is done.
|
||||
abstractmethods = []
|
||||
ancestors = list(cls.__mro__)
|
||||
ancestors.reverse() # Start with __builtin__.object
|
||||
for ancestor in ancestors:
|
||||
for clsname, clst in ancestor.__dict__.items():
|
||||
if isinstance(clst, AbstractMethod):
|
||||
abstractmethods.append(clsname)
|
||||
else:
|
||||
if clsname in abstractmethods:
|
||||
abstractmethods.remove(clsname)
|
||||
|
||||
abstractmethods.sort()
|
||||
setattr(cls, '__abstractmethods__', abstractmethods)
|
||||
|
||||
## @brief Allocator for class cls
|
||||
#
|
||||
# @param self Class object for which an instance should be
|
||||
# created.
|
||||
# @param cls Same as self.
|
||||
def new(self, cls):
|
||||
if len(cls.__abstractmethods__):
|
||||
raise NotImplementedError('Can\'t instantiate class `' + \
|
||||
cls.__name__ + '\';\n' + \
|
||||
'Abstract methods: ' + \
|
||||
", ".join(cls.__abstractmethods__))
|
||||
|
||||
return object.__new__(self)
|
|
@ -1,178 +0,0 @@
|
|||
from Abstract import *
|
||||
import sgpem
|
||||
|
||||
## @brief This is the abstract class a user-defined policy
|
||||
# should inherit from
|
||||
#
|
||||
# This class also exposes the method sort(), which can be
|
||||
# used to easily sort the queue of ready process with a
|
||||
# user-defined given compare function.
|
||||
class Policy:
|
||||
## @var Avoid instantiation of an abstract class.
|
||||
# @see Abstract.Metaclass
|
||||
__metaclass__ = Metaclass
|
||||
|
||||
## @brief Configure policy to initial values
|
||||
#
|
||||
# This is called just before a simulation starts, and is responsible
|
||||
# to define the parameters the policy wants to expose to the user.
|
||||
# For example, it may make the return value of is_preemptive configurable,
|
||||
# or register an integer value for a the time slice duration.
|
||||
#
|
||||
# Should be implemented with signature:
|
||||
# @code
|
||||
# def configure(self):
|
||||
# # function body
|
||||
# @endcode
|
||||
#
|
||||
# @see sgpem::Policy::get_parameters()
|
||||
configure = AbstractMethod('configure')
|
||||
|
||||
## @brief Sort ready processes queue
|
||||
#
|
||||
# This method is called by the scheduler at each
|
||||
# step of the simulation to sort the ready
|
||||
# processes queue.
|
||||
#
|
||||
# Should be implemented with signature:
|
||||
# @code
|
||||
# def sort_queue(self, event, queue):
|
||||
# # function body
|
||||
# @endcode
|
||||
#
|
||||
# @param event Enumeration value of type Scheduler::Event,
|
||||
# needed by some policies to know the reason of
|
||||
# the call
|
||||
# @param queue The sgpem::SchedulableQueue to be sorted.
|
||||
# Only some methods of it are implemented,
|
||||
# notably get_item_at(position),
|
||||
# swap(positionA, positionB) and size().
|
||||
#
|
||||
# @see Policy::Policy::sort()
|
||||
sort_queue = AbstractMethod('sort_queue')
|
||||
|
||||
## @brief Returns whether the policy wants to be preemptive,
|
||||
# other than by normal time slice termination
|
||||
#
|
||||
# See the return value for a complete explanation. Please
|
||||
# note how the word ``priority'' here has a general meaning:
|
||||
# it indicates every process than can bubble up the sorted
|
||||
# ready queue and come before another. So it's up to
|
||||
# Policy.sort_queue() to give it a precise meaning.
|
||||
#
|
||||
# Should be implemented with signature:
|
||||
# @code
|
||||
# def is_preemptive(self):
|
||||
# # function body
|
||||
# @endcode
|
||||
#
|
||||
# @return True If the policy declares it wants the running
|
||||
# process to be released if a process at higher priority
|
||||
# is put at the beginning of the ready processes queue
|
||||
# @return False If the policy always waits the end of the time
|
||||
# slice (or a process blocking/termination, of course) before
|
||||
# selecting a new running process, even if it has greater priority
|
||||
# than the current one
|
||||
is_preemptive = AbstractMethod('is_preemptive')
|
||||
|
||||
## @brief Returns how long is a time-slice for this policy
|
||||
#
|
||||
# A time sliced policy should return a positive integer value,
|
||||
# a policy which doesn't use slices should instead return -1.
|
||||
# You're encouraged to use a user-configurable parameter via
|
||||
# Policy.configure() if the policy is time-sliced, to ensure
|
||||
# greater flexibility.
|
||||
#
|
||||
# Should be implemented with signature:
|
||||
# @code
|
||||
# def get_time_slice(self):
|
||||
# # function body
|
||||
# @endcode
|
||||
#
|
||||
# FIXME: what happens for ``return 0''? The same as ``return 1''?
|
||||
#
|
||||
# @return -1 If the policy doesn't want to use time slices
|
||||
# @return 0+ To specify a time slice duration for this policy
|
||||
get_time_slice = AbstractMethod('get_time_slice')
|
||||
|
||||
|
||||
## @brief Returns the PolicyParameters instance you can use in
|
||||
# Policy::Policy::configure()
|
||||
#
|
||||
# @return A sgpem::PolicyParameters instance
|
||||
def get_parameters(self):
|
||||
return sgpem.Scheduler.get_instance().get_policy().get_parameters()
|
||||
|
||||
|
||||
## @brief This function implements an in-place stable sort
|
||||
# using directly SchedulableQueue methods
|
||||
#
|
||||
# The compare parameter should be a user defined binary
|
||||
# function returning either True or False, defined in one
|
||||
# of the following ways:
|
||||
# @code
|
||||
# # As a lambda anonymous function (preferred)
|
||||
# # (x and y are two SchedulableStatus objects)
|
||||
# cmpf = lambda x,y: x.someProperty() < y.someProperty()
|
||||
#
|
||||
# # As a normal *global* function
|
||||
# def compare(a,b):
|
||||
# return a.someProperty < b.someProperty()
|
||||
# cmpf = compare
|
||||
# @endcode
|
||||
#
|
||||
# The call is then simply:
|
||||
# @code
|
||||
# def sort_queue() :
|
||||
# # ...
|
||||
# self.sort(queue, cmpf)
|
||||
# @endcode
|
||||
#
|
||||
# @param self The object caller
|
||||
# @param queue The SchedulableQueue to be sorted in place
|
||||
# @param cmpf The binary function to use to compare elements
|
||||
# @returns None
|
||||
def sort(self, queue, cmpf):
|
||||
self.__recursive_qsort(queue, 0, queue.size()-1, cmpf)
|
||||
|
||||
|
||||
## @brief Recursive (private) call to perform quicksort on a
|
||||
# queue
|
||||
#
|
||||
# @param queue The queue to sort
|
||||
# @param a The initial element position of the slice
|
||||
# @param b The final element position of the slice
|
||||
# @param cmpf The user-defined compare function to employ
|
||||
# @returns None
|
||||
def __recursive_qsort(self, queue, a, b, cmpf):
|
||||
if(b>a):
|
||||
pivot = self.__partition(queue, a, b, cmpf)
|
||||
self.__recursive_qsort(queue, a, pivot-1, cmpf)
|
||||
self.__recursive_qsort(queue, pivot+1, b, cmpf)
|
||||
|
||||
|
||||
## @brief Recursive (private) call to partition a slice of the queue
|
||||
#
|
||||
# This private function (the name mangling should work)
|
||||
# naively sorts a partition of queue in place using just
|
||||
# its methods.
|
||||
#
|
||||
# Feel the love.
|
||||
#
|
||||
# @param queue The SchedulableQueue to sort
|
||||
# @param a The partition starting element position in the queue
|
||||
# @param b The partition ending element position in the queue
|
||||
# @param cmpf The binary function to use for comparing two elements
|
||||
# @return The new pivot index
|
||||
def __partition(self, queue, a, b, cmpf):
|
||||
# takes pivot element:
|
||||
right = queue.get_item_at(b)
|
||||
i = a
|
||||
for j in range(a,b): # goes from a to b-1
|
||||
if cmpf(queue.get_item_at(j), right):
|
||||
# the C++ code should do nothing if i == j:
|
||||
queue.swap(i,j)
|
||||
i = i+1
|
||||
# puts pivot in place
|
||||
queue.swap(i,b)
|
||||
return i
|
|
@ -1,109 +0,0 @@
|
|||
import mutex, thread
|
||||
import sgpem
|
||||
|
||||
## @brief This is an adapter class which acts as a proxy
|
||||
# for user-implemented policies
|
||||
#
|
||||
# At runtime, this class will be initialized with the
|
||||
# user-implemented policy, and then it will proxy the calls
|
||||
# the policy member functions on a different thread, so
|
||||
# to ensure asyncronous control.
|
||||
#
|
||||
# Instantiated in the C++ code, it is created like:
|
||||
# @code
|
||||
# adapter = ScriptAdapter(UserPolicyClass)
|
||||
# @endcode
|
||||
#
|
||||
# The user shouldn't care about this class at all.
|
||||
class ScriptAdapter :
|
||||
## @var The policy this ScriptAdapter will use for calls
|
||||
_policy = None
|
||||
|
||||
## @var The event to pass to Policy.sort_queue() after the asynchronous call
|
||||
_event = None
|
||||
|
||||
## @var Synchronized return value you can read from C++
|
||||
# when a threaded function returns
|
||||
_ret_val = None
|
||||
|
||||
## Var Testable syncronization object
|
||||
_g_mutex = mutex.mutex()
|
||||
|
||||
## @brief Constructor of ScriptAdapter
|
||||
#
|
||||
# @param self The caller object
|
||||
# @param policy A user-implemented class inheriting from Policy.Policy
|
||||
def __init__(self, policy):
|
||||
self._policy = policy()
|
||||
print 'ScriptAdapter for policy ', policy, ' loaded'
|
||||
|
||||
|
||||
## @brief Asynchronously call Policy.configure()
|
||||
#
|
||||
# @param self The caller object
|
||||
def async_configure(self):
|
||||
self._g_mutex.lock(ScriptAdapter._wrap_configure, self )
|
||||
|
||||
def _wrap_configure(self):
|
||||
thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,))
|
||||
|
||||
def _wrap_configure_callback(self):
|
||||
# call configure method
|
||||
self._policy.configure()
|
||||
self._g_mutex.unlock()
|
||||
|
||||
|
||||
## @brief Asynchronously call Policy.sort_queue()
|
||||
#
|
||||
# The queue is asked directly to the C++ sgpem::Scheduler
|
||||
# singleton, via SWIG
|
||||
#
|
||||
# @param self The caller object
|
||||
# @param event The event to pass to sort_queue
|
||||
def async_sort_queue(self, event):
|
||||
self._event = event
|
||||
self._g_mutex.lock(ScriptAdapter._wrap_sort_queue, self)
|
||||
|
||||
def _wrap_sort_queue(self):
|
||||
thread.start_new_thread(ScriptAdapter._wrap_sort_queue_callback,
|
||||
(self,self._event))
|
||||
|
||||
def _wrap_sort_queue_callback(self, event):
|
||||
# here we retrieve and pass the ready queue
|
||||
queue = sgpem.Scheduler.get_instance().get_ready_queue()
|
||||
self._policy.sort_queue(event, queue)
|
||||
self._g_mutex.unlock()
|
||||
|
||||
|
||||
## @brief Asynchronously call Policy.is_preemptive()
|
||||
#
|
||||
# @param self The caller object
|
||||
def async_is_preemptive(self):
|
||||
self._g_mutex.lock(ScriptAdapter._wrap_is_preemptive, self)
|
||||
|
||||
def _wrap_is_preemptive(self):
|
||||
thread.start_new_thread(ScriptAdapter._wrap_is_preemptive_callback, (self,))
|
||||
|
||||
def _wrap_is_preemptive_callback(self):
|
||||
self._ret_val = self._policy.is_preemptive()
|
||||
self._g_mutex.unlock()
|
||||
|
||||
## @brief Asynchronously call Policy.get_time_slice()
|
||||
#
|
||||
# @param self The caller object
|
||||
def async_get_time_slice(self):
|
||||
self._g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self)
|
||||
|
||||
def _wrap_get_time_slice(self):
|
||||
thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,))
|
||||
|
||||
def _wrap_get_time_slice_callback(self):
|
||||
self._ret_val = self._policy.get_time_slice()
|
||||
self._g_mutex.unlock()
|
||||
|
||||
## @brief Return the global shared variable with the methods' last return value
|
||||
def get_return_value(self):
|
||||
return self._ret_val
|
||||
|
||||
def mutex_test_lock(self):
|
||||
return self._g_mutex.test()
|
|
@ -1,55 +0,0 @@
|
|||
// 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))
|
||||
#define _libpyloader_LTX__global_pm (_global_pm);
|
||||
|
||||
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
|
|
@ -1,205 +0,0 @@
|
|||
// src/backend/pyloader/python_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 "python_policy.hh"
|
||||
#include <limits>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
using namespace sgpem;
|
||||
using namespace std;
|
||||
|
||||
#define WAIT_FOR (250000)
|
||||
|
||||
// WARNING : this class needs extensive and above all
|
||||
// *strong* exception checking / handling!
|
||||
|
||||
PythonPolicy::PythonPolicy(const char* name)
|
||||
: _adapter(NULL), _adapter_dict(NULL), _name(name)
|
||||
{
|
||||
PyObject* pLoadmeStr = PyString_FromString(name);
|
||||
PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr);
|
||||
Py_DECREF(pLoadmeStr);
|
||||
|
||||
if( !pUserPolicyModule )
|
||||
{
|
||||
PyErr_Print(); // Error in import
|
||||
// FIXME : don't exit abruptly, but fall back gracefully
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Dictionary with defined ``symbols'' for .pyc file
|
||||
PyObject* pUserPolicyDict = PyModule_GetDict(pUserPolicyModule);
|
||||
assert(pUserPolicyDict);
|
||||
|
||||
// Loads ScriptAdapter module and get its dictionary
|
||||
pLoadmeStr = PyString_FromString("ScriptAdapter");
|
||||
PyObject* pScriptAdapterModule = PyImport_Import(pLoadmeStr);
|
||||
Py_DECREF(pLoadmeStr);
|
||||
assert(pScriptAdapterModule);
|
||||
_adapter_dict = PyModule_GetDict(pScriptAdapterModule);
|
||||
assert(_adapter_dict);
|
||||
// We want to keep a reference to it
|
||||
Py_INCREF(_adapter_dict);
|
||||
|
||||
// Now takes the user-defined policy class from pUserPolicyDict
|
||||
PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, name);
|
||||
assert(pPolicyClass); // FIXME needs stricter checking and exception throwing
|
||||
|
||||
// Creates a new object of type ScriptAdapter :
|
||||
// takes init function from ScriptAdapter class
|
||||
PyObject* pAdapterClass = PyDict_GetItemString(_adapter_dict, "ScriptAdapter");
|
||||
PyObject* pAdapterCtorParam = PyTuple_New(1);
|
||||
Py_INCREF(pPolicyClass); // PyTuple_SetItem steals a reference
|
||||
PyTuple_SetItem(pAdapterCtorParam, 0, pPolicyClass);
|
||||
_adapter = PyInstance_New(pAdapterClass, pAdapterCtorParam, NULL);
|
||||
Py_DECREF(pAdapterCtorParam);
|
||||
assert(_adapter);
|
||||
|
||||
Py_DECREF(pUserPolicyModule);
|
||||
Py_DECREF(pScriptAdapterModule);
|
||||
|
||||
// And now, who's your daddy, huh?
|
||||
}
|
||||
|
||||
|
||||
PythonPolicy::~PythonPolicy()
|
||||
{
|
||||
if(_adapter) Py_DECREF(_adapter);
|
||||
if(_adapter_dict) Py_DECREF(_adapter_dict);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PythonPolicy::configure() throw(UserInterruptException)
|
||||
{
|
||||
PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL);
|
||||
Py_DECREF(retval);
|
||||
|
||||
wait_unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PythonPolicy::sort_queue(Scheduler::event event) const throw(UserInterruptException)
|
||||
{
|
||||
PyObject* pEvent = PyInt_FromLong(event);
|
||||
PyObject* pMethodName = PyString_FromString("async_sort_queue");
|
||||
PyObject* retval = PyObject_CallMethodObjArgs(_adapter, pMethodName, pEvent, NULL);
|
||||
|
||||
// Do minimal debugging
|
||||
if(!retval) PyErr_Print();
|
||||
else Py_DECREF(retval);
|
||||
|
||||
Py_DECREF(pMethodName);
|
||||
Py_DECREF(pEvent);
|
||||
|
||||
wait_unlock();
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring
|
||||
PythonPolicy::get_description() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PythonPolicy::is_pre_emptive() const throw(UserInterruptException)
|
||||
{
|
||||
PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL);
|
||||
Py_DECREF(retval);
|
||||
|
||||
wait_unlock();
|
||||
|
||||
// Parse return value stored in global Python object
|
||||
retval = PyObject_CallMethod(_adapter, "get_return_value", NULL);
|
||||
assert(retval);
|
||||
bool ret = PyObject_IsTrue(retval);
|
||||
Py_DECREF(retval);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PythonPolicy::get_time_slice() const throw(UserInterruptException) {
|
||||
PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL);
|
||||
Py_DECREF(retval);
|
||||
|
||||
wait_unlock();
|
||||
|
||||
// Parse return value stored in global Python object
|
||||
retval = PyObject_CallMethod(_adapter, "get_return_value", NULL);
|
||||
assert(retval);
|
||||
long tmp = PyInt_AsLong(retval);
|
||||
Py_DECREF(retval);
|
||||
|
||||
return tmp < 0 ? numeric_limits<int>::max() : static_cast<int>(tmp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PythonPolicy::wait_unlock() const throw(UserInterruptException)
|
||||
{
|
||||
PyThreadState* _save;
|
||||
int i = 0; // We give the sort_queue() three seconds max time, then...
|
||||
// we shot it stone dead! Bang.
|
||||
|
||||
bool still_locked;
|
||||
do
|
||||
{
|
||||
Py_UNBLOCK_THREADS;
|
||||
usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!!
|
||||
Py_BLOCK_THREADS;
|
||||
|
||||
PyObject* retval = PyObject_CallMethod(_adapter, "mutex_test_lock", NULL);
|
||||
assert(retval);
|
||||
still_locked = PyObject_IsTrue(retval);
|
||||
Py_DECREF(retval);
|
||||
|
||||
if(i++ > 12) /* waits for WAIT_FOR * 12 microseconds == 3 secs */
|
||||
{
|
||||
PyThreadState_Clear(_save);
|
||||
PyEval_RestoreThread(_save);
|
||||
|
||||
//Py_UNBLOCK_THREADS;
|
||||
|
||||
throw UserInterruptException("User-defined policy is "
|
||||
"taking too long to terminate.");
|
||||
}
|
||||
}
|
||||
while(still_locked);
|
||||
|
||||
// What we should really do here:
|
||||
/* do {
|
||||
enable python threads
|
||||
wait for some time...
|
||||
disable python threads
|
||||
...check if user asked for interruption, reading a
|
||||
syncronized variable...
|
||||
...if he has, break
|
||||
...else:
|
||||
if the global lock is set:
|
||||
stay in this loop
|
||||
else:
|
||||
all's went okay, can exit loop
|
||||
} */
|
||||
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
// src/backend/pyloader/python_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 PYTHON_POLICY_HH
|
||||
#define PYTHON_POLICY_HH 1
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <Python.h>
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../policy.hh"
|
||||
#include "../user_interrupt_exception.hh"
|
||||
|
||||
namespace sgpem
|
||||
{
|
||||
class PythonPolicy;
|
||||
class PythonPolicyManager;
|
||||
class UserInterruptException;
|
||||
|
||||
/** \brief A specialization of abstract class Policy
|
||||
|
||||
This class represents a policy written in Python. Its methods interact with Python interpreter.
|
||||
See the documentation of class Policy for more detailed informations.
|
||||
*/
|
||||
class SG_DLLEXPORT PythonPolicy : public Policy
|
||||
{
|
||||
public:
|
||||
PythonPolicy(const char* name);
|
||||
virtual ~PythonPolicy();
|
||||
|
||||
/**
|
||||
Calls the method \c async_configure
|
||||
*/
|
||||
void configure() throw(UserInterruptException);
|
||||
|
||||
/**
|
||||
Calls the method \c async_sort_queue
|
||||
*/
|
||||
void sort_queue(Scheduler::event) const throw(UserInterruptException);
|
||||
|
||||
/**
|
||||
\returns A textual description of this policy.
|
||||
*/
|
||||
Glib::ustring get_description() const;
|
||||
|
||||
/**
|
||||
\returns \c TRUE if the policy is preemptive.
|
||||
\returns \c FALSE if the policy is not preemptive.
|
||||
*/
|
||||
bool is_pre_emptive() const throw(UserInterruptException);
|
||||
|
||||
/**
|
||||
\returns The integer value of its time-slice.
|
||||
*/
|
||||
int get_time_slice() const throw(UserInterruptException);
|
||||
|
||||
private:
|
||||
PythonPolicy(const PythonPolicy&);
|
||||
PythonPolicy& operator=(const PythonPolicy&);
|
||||
|
||||
void wait_unlock() const throw(UserInterruptException);
|
||||
|
||||
PyObject* _adapter;
|
||||
PyObject* _adapter_dict;
|
||||
|
||||
Glib::ustring _name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
// src/backend/pyloader/python_policy_manager.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 "python_policy_manager.hh"
|
||||
#include "../global_settings.hh"
|
||||
|
||||
#include <Python.h>
|
||||
#include <glibmm/ustring.h>
|
||||
#include <glibmm/timer.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
using namespace sgpem;
|
||||
|
||||
|
||||
|
||||
// Concatenate a string with all the policies directories
|
||||
struct pol_dirs_concat : public std::unary_function<void, const Glib::ustring&>
|
||||
{
|
||||
public:
|
||||
pol_dirs_concat(Glib::ustring& cat) : _cat(cat) {}
|
||||
void operator()(const Glib::ustring& add)
|
||||
{
|
||||
// Please note that this string will end finishing with
|
||||
// and additional ","!
|
||||
_cat += "'" + add + "', ";
|
||||
}
|
||||
private:
|
||||
Glib::ustring& _cat;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//static object
|
||||
PythonPolicyManager* PythonPolicyManager::_instance = NULL;
|
||||
|
||||
|
||||
PythonPolicyManager::PythonPolicyManager()
|
||||
: _initialized(false)
|
||||
{
|
||||
PyEval_InitThreads();
|
||||
}
|
||||
|
||||
|
||||
PythonPolicyManager* const
|
||||
PythonPolicyManager::get_instance()
|
||||
{
|
||||
if(!_instance)
|
||||
_instance = new PythonPolicyManager();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
||||
Policy&
|
||||
PythonPolicyManager::get_policy()
|
||||
{
|
||||
// FIXME : assumes that _python_policy is always != NULL!
|
||||
return *_python_policy;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PythonPolicyManager::init()
|
||||
{
|
||||
if(_initialized)
|
||||
// No-op
|
||||
return;
|
||||
|
||||
Py_Initialize();
|
||||
_initialized = true;
|
||||
|
||||
// The following lines are ugly, but necessary if we use
|
||||
// non-standard installation directories. Theoretically,
|
||||
// it should be up to the user to set correct
|
||||
// environment variables.
|
||||
// FIXME: find better way to achieve this.
|
||||
|
||||
Glib::ustring importdirs = "import sys\n"
|
||||
"sys.path[:0] = [ ";
|
||||
for_each(GlobalSettings::instance().policies_dir_begin(),
|
||||
GlobalSettings::instance().policies_dir_end(),
|
||||
pol_dirs_concat(importdirs));
|
||||
importdirs += " '" MODDIR "' ]\n";
|
||||
|
||||
PyRun_SimpleString(importdirs.c_str());
|
||||
|
||||
// Okay, here we go.
|
||||
// Black magic at work.
|
||||
|
||||
// FIXME : Hardcoded policy name
|
||||
char* policy_name = "fcfs";
|
||||
//char* policy_name = "sjf";
|
||||
_python_policy = std::auto_ptr<PythonPolicy>(new PythonPolicy(policy_name));
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
// src/backend/pyloader/python_policy_manager.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 PYTHON_POLICY_MANAGER_HH
|
||||
#define PYTHON_POLICY_MANAGER_HH 1
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "../policy_manager.hh"
|
||||
#include "python_policy.hh"
|
||||
|
||||
namespace sgpem
|
||||
{
|
||||
//class PolicyManager;
|
||||
class PythonPolicyManager;
|
||||
|
||||
/** \brief Manages Python user-implemented policies
|
||||
*
|
||||
* This singleton manages the creation and destruction
|
||||
* of a Python policy.
|
||||
*/
|
||||
class SG_DLLEXPORT PythonPolicyManager : public PolicyManager
|
||||
{
|
||||
public:
|
||||
/** \brief Returns a reference to the active policy.
|
||||
*
|
||||
* For the moment, it will sufficit to keep and return
|
||||
* just one Policy for PolicyManager.
|
||||
* In the next milestones it will be possible to manage
|
||||
* more than one, and to retrieve the correct Policy by
|
||||
* passing a unique ID.
|
||||
*/
|
||||
Policy& get_policy();
|
||||
|
||||
/** \brief Initialize the Python interpreter.
|
||||
*
|
||||
* If the interpreter has already been initialized, it terminates it, cleanups old policies,
|
||||
* and restarts it.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/** \brief Returns the singleton instance of
|
||||
* PythonPolicyManager.
|
||||
*
|
||||
* Please note that the first time you'll request
|
||||
* it, it will be still uninitialized.
|
||||
* @see init()
|
||||
*/
|
||||
static PythonPolicyManager* const get_instance();
|
||||
|
||||
protected:
|
||||
/** The selected and active PyhonPolicy object. */
|
||||
PythonPolicyManager();
|
||||
std::auto_ptr<PythonPolicy> _python_policy;
|
||||
|
||||
private:
|
||||
PythonPolicyManager(const PythonPolicyManager&);
|
||||
PythonPolicyManager& operator=(const PythonPolicyManager&);
|
||||
|
||||
/** Singleton support. */
|
||||
static PythonPolicyManager* _instance;
|
||||
|
||||
bool _initialized;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
%module sgpem
|
||||
%{
|
||||
#include "policy.hh"
|
||||
#include "policy_parameters.hh"
|
||||
#include "schedulable.hh"
|
||||
#include "schedulable_list.hh"
|
||||
#include "schedulable_status.hh"
|
||||
#include "scheduler.hh"
|
||||
%}
|
||||
|
||||
/* NOTE : passing Unicode strings to C++ methods calling them
|
||||
* from Python results in a SIGSEGV. You've been warned!
|
||||
* (Investigate if this can be fixed, else please report it in
|
||||
* the sgpem user manual)
|
||||
*/
|
||||
|
||||
/** Due to the relatively new support for namespaces in SWIG,
|
||||
* make sure to include the full visibility signature when
|
||||
* returning / passing parameters from / to functions with
|
||||
* objects different to the one you're declaring.
|
||||
*/
|
||||
|
||||
namespace std {
|
||||
class exception {
|
||||
public:
|
||||
virtual const char* what() const throw();
|
||||
private:
|
||||
exception();
|
||||
};
|
||||
|
||||
class runtime_error : public std::exception {
|
||||
public:
|
||||
virtual const char* what() const throw();
|
||||
private:
|
||||
runtime_error();
|
||||
};
|
||||
}
|
||||
|
||||
namespace sgpem {
|
||||
|
||||
class Policy {
|
||||
public:
|
||||
virtual ~Policy() = 0;
|
||||
sgpem::PolicyParameters& get_parameters();
|
||||
};
|
||||
|
||||
// --------------------------------------------
|
||||
class PolicyParametersException : public std::runtime_error {
|
||||
public:
|
||||
PolicyParametersException(char* msg);
|
||||
%rename (__str__) what;
|
||||
virtual const char* what();
|
||||
}; //~ class PolicyParametersException
|
||||
|
||||
// --------------------------------------------
|
||||
class PolicyParameters
|
||||
{
|
||||
public:
|
||||
//methods to CREATE PARAMETERS
|
||||
// (rewrapped correctly for SWIG usage)
|
||||
%ignore register_int(const Glib::ustring&, const int&,
|
||||
const int&, const bool&, const int&);
|
||||
%ignore register_float(const Glib::ustring&, const float&,
|
||||
const float&, const bool&, const float&);
|
||||
%ignore register_string(const Glib::ustring&, const bool&,
|
||||
const char*);
|
||||
|
||||
%extend {
|
||||
void register_int(const char* name,
|
||||
const int& lower_bound,
|
||||
const int& upper_bound,
|
||||
const bool& required,
|
||||
const int& default_value = 0)
|
||||
{
|
||||
self->register_int(name, lower_bound, upper_bound,
|
||||
required, default_value);
|
||||
}
|
||||
|
||||
void register_float(const char* name,
|
||||
const float& lower_bound,
|
||||
const float& upper_bound,
|
||||
const bool& required,
|
||||
const float& default_value = 0.0f)
|
||||
{
|
||||
self->register_float(name, lower_bound, upper_bound,
|
||||
required, default_value);
|
||||
}
|
||||
|
||||
void register_string(const char* name,
|
||||
const bool& required,
|
||||
const char* default_value = "")
|
||||
{
|
||||
self->register_string(name, required, default_value);
|
||||
}
|
||||
}
|
||||
|
||||
//methods to SET the VALUE of PARAMETERS
|
||||
// (rewrapped correctly for SWIG usage)
|
||||
%ignore set_int(const Glib::ustring&, const int&);
|
||||
%ignore set_float(const Glib::ustring&, const float&);
|
||||
%ignore set_string(const Glib::ustring&, const Glib::ustring&);
|
||||
|
||||
%extend {
|
||||
bool set_int(const char* name, const int& value)
|
||||
{ return self->set_int(name, value); }
|
||||
bool set_float(const char* name, const float& value)
|
||||
{ return self->set_float(name, value); }
|
||||
bool set_string(const char* name, const char* value)
|
||||
{ return self->set_string(name, value); }
|
||||
}
|
||||
|
||||
//methods to GET the VALUE of PARAMETERS
|
||||
// (rewrapped correctly for SWIG usage)
|
||||
%ignore get_int(const Glib::ustring&) const;
|
||||
%ignore get_float(const Glib::ustring&) const;
|
||||
%ignore get_string(const Glib::ustring&) const;
|
||||
|
||||
%extend {
|
||||
int get_int(const char* name) const
|
||||
{ return self->get_int(name); }
|
||||
float get_float(const char* name) const
|
||||
{ return self->get_float(name); }
|
||||
const char* get_string(const char* name) const
|
||||
{ return self->get_string(name).c_str(); }
|
||||
}
|
||||
|
||||
}; //~ class PolicyParameters
|
||||
|
||||
// --------------------------------------------
|
||||
class Schedulable
|
||||
{
|
||||
public:
|
||||
virtual ~Schedulable() = 0;
|
||||
|
||||
virtual unsigned int get_arrival_time() const;
|
||||
int get_priority() const;
|
||||
unsigned int get_total_cpu_time() const;
|
||||
|
||||
%ignore Schedulable::get_name() const;
|
||||
%extend {
|
||||
const char* get_name() const
|
||||
{ return self->get_name().c_str(); }
|
||||
}
|
||||
}; //~ class Schedulable
|
||||
|
||||
|
||||
// --------------------------------------------
|
||||
class SchedulableList
|
||||
{
|
||||
public:
|
||||
unsigned int size() const;
|
||||
const sgpem::SchedulableStatus* get_item_at(const unsigned int&) const;
|
||||
void swap(unsigned int positionA, unsigned int positionB) throw();
|
||||
|
||||
private:
|
||||
// Avoid instantiation and copy
|
||||
SchedulableList();
|
||||
SchedulableList(const SchedulableList&);
|
||||
SchedulableList& operator=(const SchedulableList&);
|
||||
~SchedulableList();
|
||||
}; //~ class Schedulable
|
||||
|
||||
// ---------------------------------------------
|
||||
class SchedulableStatus
|
||||
{
|
||||
public:
|
||||
enum state
|
||||
{
|
||||
state_running = 1<<0,
|
||||
state_ready = 1<<1,
|
||||
state_blocked = 1<<2,
|
||||
state_future = 1<<3,
|
||||
state_terminated = 1<<4
|
||||
};
|
||||
|
||||
SchedulableStatus(const SchedulableStatus& obj);
|
||||
|
||||
int get_cpu_time_left() const;
|
||||
int get_last_scheduled() const;
|
||||
state get_state() const;
|
||||
const sgpem::Schedulable* get_schedulable() const;
|
||||
};
|
||||
|
||||
// ---------------------------------------------
|
||||
class Scheduler {
|
||||
public:
|
||||
sgpem::Policy& get_policy();
|
||||
static sgpem::Scheduler& get_instance();
|
||||
sgpem::SchedulableList* get_ready_queue();
|
||||
private:
|
||||
Scheduler();
|
||||
~Scheduler();
|
||||
};
|
||||
|
||||
} //~ namespace sgpem
|
|
@ -1,42 +0,0 @@
|
|||
# src/builtin-policies/fcfs.py - 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
|
||||
|
||||
|
||||
from Policy import Policy
|
||||
import sys
|
||||
|
||||
class fcfs(Policy) :
|
||||
def __init__(self):
|
||||
pass;
|
||||
|
||||
def configure(self):
|
||||
print 'No options to configure for fcfs'
|
||||
|
||||
def is_preemptive(self):
|
||||
return False
|
||||
|
||||
def get_time_slice(self):
|
||||
return -2
|
||||
|
||||
def sort_queue(self, event, queue):
|
||||
cmpf = lambda a, b: \
|
||||
a.get_schedulable().get_arrival_time() < \
|
||||
b.get_schedulable().get_arrival_time()
|
||||
self.sort(queue,cmpf)
|
|
@ -1,42 +0,0 @@
|
|||
# src/builtin-policies/sjf.py - 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
|
||||
|
||||
|
||||
from Policy import Policy
|
||||
import sys
|
||||
|
||||
class sjf(Policy) :
|
||||
def __init__(self):
|
||||
pass;
|
||||
|
||||
def configure(self):
|
||||
print 'No options to configure for fcfs'
|
||||
|
||||
def is_preemptive(self):
|
||||
return False
|
||||
|
||||
def get_time_slice(self):
|
||||
return -1
|
||||
|
||||
def sort_queue(self, event, queue):
|
||||
cmpf = lambda a, b: \
|
||||
a.get_cpu_time_left() < \
|
||||
b.get_cpu_time_left()
|
||||
self.sort(queue,cmpf)
|
|
@ -1,20 +0,0 @@
|
|||
from Policy import Policy
|
||||
import sys
|
||||
|
||||
class python_loader_configure(Policy) :
|
||||
def __init__(self):
|
||||
pass;
|
||||
|
||||
def configure(self):
|
||||
print "[II] Entering willingly an endless loop."
|
||||
while True:
|
||||
pass
|
||||
|
||||
def is_preemptive(self):
|
||||
return False
|
||||
|
||||
def get_time_slice(self):
|
||||
return -1
|
||||
|
||||
def sort_queue(self, event, queue):
|
||||
pass
|
|
@ -1,21 +0,0 @@
|
|||
from Policy import Policy
|
||||
import sys
|
||||
|
||||
class python_loader_get_time_slice(Policy) :
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure(self):
|
||||
pass
|
||||
|
||||
def is_preemptive(self):
|
||||
return False
|
||||
|
||||
def get_time_slice(self):
|
||||
print "[II] Entering willingly an endless loop."
|
||||
while True:
|
||||
pass
|
||||
return -1
|
||||
|
||||
def sort_queue(self, event, queue):
|
||||
pass
|
|
@ -1,21 +0,0 @@
|
|||
from Policy import Policy
|
||||
import sys
|
||||
|
||||
class python_loader_is_preemptive(Policy) :
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure(self):
|
||||
pass
|
||||
|
||||
def is_preemptive(self):
|
||||
print "[II] Entering willingly an endless loop."
|
||||
while True:
|
||||
pass
|
||||
return False
|
||||
|
||||
def get_time_slice(self):
|
||||
return -1
|
||||
|
||||
def sort_queue(self, event, queue):
|
||||
pass
|
|
@ -1,20 +0,0 @@
|
|||
from Policy import Policy
|
||||
import sys
|
||||
|
||||
class python_loader_sort_queue(Policy) :
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure(self):
|
||||
pass
|
||||
|
||||
def is_preemptive(self):
|
||||
return False
|
||||
|
||||
def get_time_slice(self):
|
||||
return -1
|
||||
|
||||
def sort_queue(self, event, queue):
|
||||
print "[II] Entering willingly an endless loop."
|
||||
while True:
|
||||
pass
|
|
@ -1,113 +0,0 @@
|
|||
// src/testsuite/test-python_loader.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
|
||||
|
||||
/* This executable tests for workingness of the PythonPolicyManager
|
||||
* class and its closely related cousins. More documentation to be written
|
||||
* here, thanks very much. */
|
||||
|
||||
#include "backend/pyloader/python_policy_manager.hh"
|
||||
#include "backend/pyloader/python_policy.hh"
|
||||
#include "backend/global_settings.hh"
|
||||
#include "backend/schedulable_list.hh"
|
||||
#include "backend/scheduler.hh"
|
||||
#include "backend/user_interrupt_exception.hh"
|
||||
#include "templates/smartp.hh"
|
||||
|
||||
#include <Python.h>
|
||||
#include <glibmm/module.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
// FIXME: Eeeeh? Why does this work without explicit namespace resolving?
|
||||
// Is there some using declaration in included HEADERS?? Aaaaagh!
|
||||
|
||||
class TestPythonPolicyManager : public PythonPolicyManager {
|
||||
public:
|
||||
void test_init(const char* policy_name) {
|
||||
init();
|
||||
_python_policy = std::auto_ptr<PythonPolicy>(new PythonPolicy(policy_name));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char** argv) {
|
||||
using namespace sgpem;
|
||||
using namespace std;
|
||||
|
||||
if(argc != 2) {
|
||||
std::cout << "[EE] Usage:\n\t" << argv[0] <<
|
||||
" path/to/uninstalled/policies" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
// Add argv[1] as the directory to search for uninstalled policies
|
||||
sgpem::GlobalSettings::instance().add_policies_dir(argv[1]);
|
||||
|
||||
// Self-register itself to Scheduler, however we don't care about it
|
||||
TestPythonPolicyManager polman;
|
||||
|
||||
try
|
||||
{
|
||||
polman.test_init("python_loader_configure");
|
||||
polman.get_policy().configure();
|
||||
}
|
||||
catch(UserInterruptException e)
|
||||
{
|
||||
cout << "configure: Caught UserInterruptException" << endl;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
polman.test_init("python_loader_is_preemptive");
|
||||
polman.get_policy().is_pre_emptive();
|
||||
}
|
||||
catch(UserInterruptException e)
|
||||
{
|
||||
cout << "is_preemptive: Caught UserInterruptException" << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
polman.test_init("python_loader_get_time_slice");
|
||||
polman.get_policy().get_time_slice();
|
||||
}
|
||||
catch(UserInterruptException e)
|
||||
{
|
||||
cout << "get_time_slice: Caught UserInterruptException" << endl;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
SchedulableList sl;
|
||||
polman.test_init("python_loader_sort_queue");
|
||||
polman.get_policy().sort_queue(Scheduler::event_schedulable_arrival);
|
||||
}
|
||||
catch(UserInterruptException e)
|
||||
{
|
||||
cout << "sort_queue: Caught UserInterruptException" << endl;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue