- Add documentation for classes:
- (C++) PythonPolicyManager - (Python) Policy, ScriptAdapter, fcfs git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@408 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
9091035003
commit
e2211907f5
|
@ -3,28 +3,123 @@ from Abstract import *
|
||||||
## @brief This is the abstract class a user-defined policy
|
## @brief This is the abstract class a user-defined policy
|
||||||
# should inherit from
|
# should inherit from
|
||||||
#
|
#
|
||||||
# This class also exposes the method sort, which can be
|
# This class also exposes the method sort(), which can be
|
||||||
# used to easily sort the queue of ready process with a
|
# used to easily sort the queue of ready process with a
|
||||||
# given compare function
|
# user-defined given compare function.
|
||||||
class Policy:
|
class Policy:
|
||||||
## @var Avoid instantiation of an abstract class
|
## @var Avoid instantiation of an abstract class.
|
||||||
|
# @see Abstract.Metaclass
|
||||||
__metaclass__ = Metaclass
|
__metaclass__ = Metaclass
|
||||||
|
|
||||||
configure = AbstractMethod('configure')
|
## @brief Configure policy to initial values
|
||||||
sort_queue = AbstractMethod('sort_queue')
|
|
||||||
is_preemptive = AbstractMethod('is_preemptive')
|
|
||||||
get_time_slice = AbstractMethod('get_time_slice')
|
|
||||||
|
|
||||||
## @brief this function implements a quicksort in place
|
|
||||||
# using the SchedulableQueue methods
|
|
||||||
#
|
#
|
||||||
# The compare parameter should be a user defined function
|
# This is called just before a simulation starts, and is responsible
|
||||||
# name returning either True or False, defined like:
|
# 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.
|
||||||
|
#
|
||||||
|
# @warning How do the user access get_parameters()?
|
||||||
|
#
|
||||||
|
# Should be implemented with signature:
|
||||||
# @code
|
# @code
|
||||||
# def compare(SchedulableA,SchedulableB):
|
# def configure(self):
|
||||||
# return SchedulableA.someProperty() < SchedulableB.someProperty()
|
# # function body
|
||||||
# @endcode
|
# @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.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 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)
|
||||||
|
# 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 queue The SchedulableQueue to be sorted in place
|
||||||
# @param cmpf The binary function to use to compare elements
|
# @param cmpf The binary function to use to compare elements
|
||||||
# @returns None
|
# @returns None
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import mutex, thread
|
import mutex, thread
|
||||||
import sgpem
|
import sgpem
|
||||||
|
|
||||||
|
## Var Global syncronization object
|
||||||
_g_mutex = mutex.mutex()
|
_g_mutex = mutex.mutex()
|
||||||
|
|
||||||
## @val Synchronized return value you can read from C++
|
## @var Synchronized return value you can read from C++
|
||||||
# when a threaded function returns
|
# when a threaded function returns
|
||||||
_ret_val = None
|
_ret_val = None
|
||||||
|
|
||||||
|
@ -15,18 +16,32 @@ _ret_val = None
|
||||||
# the policy member functions on a different thread, so
|
# the policy member functions on a different thread, so
|
||||||
# to ensure asyncronous control.
|
# to ensure asyncronous control.
|
||||||
#
|
#
|
||||||
# Instantiated in the C++ code, it should be instantiated like:
|
# Instantiated in the C++ code, it is created like:
|
||||||
# @code
|
# @code
|
||||||
# adapter = ScriptAdapter(UserPolicyClass)
|
# adapter = ScriptAdapter(UserPolicyClass)
|
||||||
# @endcode
|
# @endcode
|
||||||
|
#
|
||||||
|
# The user shouldn't care about this class at all.
|
||||||
class ScriptAdapter :
|
class ScriptAdapter :
|
||||||
|
## @var The policy this ScriptAdapter will use for calls
|
||||||
_policy = None
|
_policy = None
|
||||||
|
|
||||||
|
## @var The event to pass to Policy.sort_queue() after the asynchronous call
|
||||||
_event = None
|
_event = None
|
||||||
|
|
||||||
|
|
||||||
|
## @brief Constructor of ScriptAdapter
|
||||||
|
#
|
||||||
|
# @param self The caller object
|
||||||
|
# @param policy A user-implemented class inheriting from Policy.Policy
|
||||||
def __init__(self, policy):
|
def __init__(self, policy):
|
||||||
self._policy = policy()
|
self._policy = policy()
|
||||||
print 'ScriptAdapter for policy ', policy, ' loaded'
|
print 'ScriptAdapter for policy ', policy, ' loaded'
|
||||||
|
|
||||||
|
|
||||||
|
## @brief Asynchronously call Policy.configure()
|
||||||
|
#
|
||||||
|
# @param self The caller object
|
||||||
def async_configure(self):
|
def async_configure(self):
|
||||||
_g_mutex.lock(ScriptAdapter._wrap_configure, self )
|
_g_mutex.lock(ScriptAdapter._wrap_configure, self )
|
||||||
|
|
||||||
|
@ -38,6 +53,14 @@ class ScriptAdapter :
|
||||||
self._policy.configure()
|
self._policy.configure()
|
||||||
_g_mutex.unlock()
|
_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):
|
def async_sort_queue(self, event):
|
||||||
self._event = event
|
self._event = event
|
||||||
_g_mutex.lock(ScriptAdapter._wrap_sort_queue, self)
|
_g_mutex.lock(ScriptAdapter._wrap_sort_queue, self)
|
||||||
|
@ -52,6 +75,10 @@ class ScriptAdapter :
|
||||||
self._policy.sort_queue(event, queue)
|
self._policy.sort_queue(event, queue)
|
||||||
_g_mutex.unlock()
|
_g_mutex.unlock()
|
||||||
|
|
||||||
|
|
||||||
|
## @brief Asynchronously call Policy.is_preemptive()
|
||||||
|
#
|
||||||
|
# @param self The caller object
|
||||||
def async_is_preemptive(self):
|
def async_is_preemptive(self):
|
||||||
_g_mutex.lock(ScriptAdapter._wrap_is_preemptive, self)
|
_g_mutex.lock(ScriptAdapter._wrap_is_preemptive, self)
|
||||||
|
|
||||||
|
@ -62,6 +89,10 @@ class ScriptAdapter :
|
||||||
_ret_val = self._policy.is_preemptive()
|
_ret_val = self._policy.is_preemptive()
|
||||||
_g_mutex.unlock()
|
_g_mutex.unlock()
|
||||||
|
|
||||||
|
|
||||||
|
## @brief Asynchronously call Policy.get_time_slice()
|
||||||
|
#
|
||||||
|
# @param self The caller object
|
||||||
def async_get_time_slice(self):
|
def async_get_time_slice(self):
|
||||||
_g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self)
|
_g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self)
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,38 @@ namespace sgpem
|
||||||
//class PolicyManager;
|
//class PolicyManager;
|
||||||
class PythonPolicyManager;
|
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
|
class SG_DLLEXPORT PythonPolicyManager : public PolicyManager
|
||||||
{
|
{
|
||||||
public:
|
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();
|
Policy& get_policy();
|
||||||
void init();
|
|
||||||
PyObject* get_py_dict();
|
|
||||||
|
|
||||||
|
/** \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();
|
static PythonPolicyManager* const get_instance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -47,7 +72,10 @@ namespace sgpem
|
||||||
PythonPolicyManager(const PythonPolicyManager&);
|
PythonPolicyManager(const PythonPolicyManager&);
|
||||||
PythonPolicyManager& operator=(const PythonPolicyManager&);
|
PythonPolicyManager& operator=(const PythonPolicyManager&);
|
||||||
|
|
||||||
|
/** Singleton support. */
|
||||||
static PythonPolicyManager* _instance;
|
static PythonPolicyManager* _instance;
|
||||||
|
|
||||||
|
/** The selected and active PyhonPolicy object. */
|
||||||
std::auto_ptr<PythonPolicy> _python_policy;
|
std::auto_ptr<PythonPolicy> _python_policy;
|
||||||
|
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
|
|
|
@ -16,18 +16,18 @@ class fcfs(Policy) :
|
||||||
def sort_queue(self, event, queue):
|
def sort_queue(self, event, queue):
|
||||||
print 'Entering sort_queue'
|
print 'Entering sort_queue'
|
||||||
print queue.size()
|
print queue.size()
|
||||||
|
print queue.get_item_at(0)
|
||||||
print dir(queue.get_item_at(0))
|
print dir(queue.get_item_at(0))
|
||||||
for i in range(0, queue.size()):
|
for i in range(0, queue.size()):
|
||||||
ss = queue.get_item_at(i)
|
ss = queue.get_item_at(i)
|
||||||
print ss.get_schedulable().get_name()
|
print ss.get_schedulable().get_name()
|
||||||
cmpf = lambda a, b: \
|
# Uncomment this to try the qsort algorithm with FCFS
|
||||||
a.get_schedulable().get_arrival_time() < \
|
#cmpf = lambda a, b: \
|
||||||
b.get_schedulable().get_arrival_time()
|
# a.get_schedulable().get_arrival_time() < \
|
||||||
try:
|
# b.get_schedulable().get_arrival_time()
|
||||||
self.sort(queue,cmpf)
|
#try:
|
||||||
except:
|
# self.sort(queue,cmpf)
|
||||||
print "Unexpected error:", sys.exc_info()[0]
|
#except:
|
||||||
raise
|
# print "Unexpected error:", sys.exc_info()[0]
|
||||||
for i in range(0, queue.size()):
|
# raise
|
||||||
ss = queue.get_item_at(i)
|
|
||||||
print ss.get_schedulable().get_name()
|
|
||||||
|
|
Loading…
Reference in New Issue