- 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:
tchernobog 2006-02-23 18:55:14 +00:00
parent 9091035003
commit e2211907f5
4 changed files with 188 additions and 34 deletions

View File

@ -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

View File

@ -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 )
@ -37,7 +52,15 @@ class ScriptAdapter :
# call configure method # call configure method
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)
@ -61,7 +88,11 @@ class ScriptAdapter :
def _wrap_is_preemptive_callback(self): def _wrap_is_preemptive_callback(self):
_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)

View File

@ -32,14 +32,39 @@ 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();
/** \brief Initialize the Python interpreter.
*
* If the interpreter has already been initialized, it terminates it, cleanups old policies,
* and restarts it.
*/
void init(); void init();
PyObject* get_py_dict();
/** \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;

View File

@ -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()