- Finish implementing async setup for Python policies' access
- Correct method names for the Python policy (design problem?) - Compiles, but can't run it on this machine. I'll test it later (and I expect quite a lot of SIGSEGVs). git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@382 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
882a6acf5e
commit
8f655f2f69
|
@ -50,6 +50,4 @@ namespace sgpem
|
||||||
|
|
||||||
}//~ namespace sgpem
|
}//~ namespace sgpem
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -41,22 +41,21 @@ namespace sgpem
|
||||||
class SG_DLLEXPORT Policy
|
class SG_DLLEXPORT Policy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Policy();
|
virtual ~Policy();
|
||||||
|
|
||||||
virtual void configure() = 0;
|
virtual void configure() = 0;
|
||||||
virtual void sort_queue(sgpem::Scheduler::event) const = 0;
|
virtual void sort_queue(sgpem::Scheduler::event) const = 0;
|
||||||
int get_id() const;
|
int get_id() const;
|
||||||
virtual Glib::ustring get_description() const = 0;
|
virtual Glib::ustring get_description() const = 0;
|
||||||
virtual bool is_pre_emptive() const = 0;
|
virtual bool is_pre_emptive() const = 0;
|
||||||
virtual int get_time_slice() const = 0;
|
virtual int get_time_slice() const = 0;
|
||||||
virtual void set_time_slice(const int&) = 0;
|
virtual void set_time_slice(const int&) = 0;
|
||||||
|
|
||||||
PolicyParameters& get_parameters();
|
|
||||||
|
|
||||||
|
PolicyParameters& get_parameters();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PolicyParameters _parameters;
|
PolicyParameters _parameters;
|
||||||
int _id;
|
int _id;
|
||||||
};
|
};
|
||||||
|
|
||||||
}//~ namespace sgpem
|
}//~ namespace sgpem
|
||||||
|
|
|
@ -7,5 +7,5 @@ class Policy:
|
||||||
configure = AbstractMethod('configure')
|
configure = AbstractMethod('configure')
|
||||||
sort_queue = AbstractMethod('sort_queue')
|
sort_queue = AbstractMethod('sort_queue')
|
||||||
is_preemptive = AbstractMethod('is_preemptive')
|
is_preemptive = AbstractMethod('is_preemptive')
|
||||||
is_time_sliced = AbstractMethod('is_time_sliced')
|
get_time_slice = AbstractMethod('get_time_slice')
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,10 @@ import sgpem
|
||||||
|
|
||||||
_g_mutex = mutex.mutex()
|
_g_mutex = mutex.mutex()
|
||||||
|
|
||||||
|
## @val Synchronized return value you can read from C++
|
||||||
|
# when a threaded function returns
|
||||||
|
_ret_val = None
|
||||||
|
|
||||||
## @brief This is an adapter class which acts as a proxy
|
## @brief This is an adapter class which acts as a proxy
|
||||||
# for user-implemented policies
|
# for user-implemented policies
|
||||||
#
|
#
|
||||||
|
@ -29,6 +33,7 @@ class ScriptAdapter :
|
||||||
|
|
||||||
def _wrap_configure(self):
|
def _wrap_configure(self):
|
||||||
thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,))
|
thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,))
|
||||||
|
|
||||||
def _wrap_configure_callback(self):
|
def _wrap_configure_callback(self):
|
||||||
# call configure method
|
# call configure method
|
||||||
self._policy.configure()
|
self._policy.configure()
|
||||||
|
@ -53,17 +58,15 @@ class ScriptAdapter :
|
||||||
thread.start_new_thread(ScriptAdapter._wrap_is_preemptible_callback, (self,))
|
thread.start_new_thread(ScriptAdapter._wrap_is_preemptible_callback, (self,))
|
||||||
|
|
||||||
def _wrap_is_preemptible_callback(self):
|
def _wrap_is_preemptible_callback(self):
|
||||||
# FIXME : here we should return the call value
|
_ret_val = self._policy.is_preemptible()
|
||||||
self._policy.is_preemptible()
|
|
||||||
_g_mutex.unlock()
|
_g_mutex.unlock()
|
||||||
|
|
||||||
def async_is_timesliced(self):
|
def async_get_time_slice(self):
|
||||||
_g_mutex.lock(ScriptAdapter._wrap_is_timesliced, self)
|
_g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self)
|
||||||
|
|
||||||
def _wrap_is_timesliced(self):
|
def _wrap_get_time_slice(self):
|
||||||
thread.start_new_thread(ScriptAdapter._wrap_is_timesliced_callback, (self,))
|
thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,))
|
||||||
|
|
||||||
def _wrap_is_timesliced_callback(self):
|
def _wrap_get_time_slice_callback(self):
|
||||||
# FIXME : return value!
|
_ret_val = self._policy.get_time_slice()
|
||||||
self._policy.is_timesliced()
|
|
||||||
_g_mutex.unlock()
|
_g_mutex.unlock()
|
||||||
|
|
|
@ -19,10 +19,159 @@
|
||||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "python_policy.hh"
|
#include "python_policy.hh"
|
||||||
|
#include <unistd.h>
|
||||||
using namespace sgpem;
|
using namespace sgpem;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
PythonPolicy::PythonPolicy()
|
// WARNING : this class needs extensive and above all
|
||||||
|
// *strong* exception checking / handling!
|
||||||
|
|
||||||
|
PythonPolicy::PythonPolicy(const char* name)
|
||||||
|
: _adapter(NULL), _adapter_dict(NULL),
|
||||||
|
_lock(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 even if we decref
|
||||||
|
// its containing module
|
||||||
|
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
|
||||||
|
|
||||||
|
// Save a reference to the global lock
|
||||||
|
_lock = PyDict_GetItemString(_adapter_dict, "_g_mutex");
|
||||||
|
assert(_lock);
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
{
|
||||||
|
PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL);
|
||||||
|
Py_DECREF(retval);
|
||||||
|
wait_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonPolicy::sort_queue(Scheduler::event event) const
|
||||||
|
{
|
||||||
|
PyObject* pEvent = PyInt_FromLong(event);
|
||||||
|
PyObject* pMethodName = PyString_FromString("async_sort_queue");
|
||||||
|
PyObject* retval = PyObject_CallMethodObjArgs(_adapter, pMethodName, pEvent, NULL);
|
||||||
|
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 {
|
||||||
|
PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL);
|
||||||
|
Py_DECREF(retval);
|
||||||
|
|
||||||
|
wait_unlock();
|
||||||
|
|
||||||
|
// Parse return value stored in global Python object
|
||||||
|
retval = PyDict_GetItemString(_adapter_dict, "_ret_val");
|
||||||
|
return static_cast<bool>(PyInt_AsLong(retval));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
PythonPolicy::get_time_slice() const {
|
||||||
|
PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL);
|
||||||
|
Py_DECREF(retval);
|
||||||
|
|
||||||
|
wait_unlock();
|
||||||
|
|
||||||
|
// Parse return value stored in global Python object
|
||||||
|
retval = PyDict_GetItemString(_adapter_dict, "_ret_val");
|
||||||
|
return static_cast<int>(PyInt_AsLong(retval));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonPolicy::set_time_slice(const int&)
|
||||||
|
{
|
||||||
|
throw "The design is wrong, and I shouldn't be called.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PythonPolicy::wait_unlock() const
|
||||||
|
{
|
||||||
|
PyThreadState *_save;
|
||||||
|
Py_UNBLOCK_THREADS
|
||||||
|
sleep(5); // hack'a'ton! magggggiccc nummmbeeerrrrrs!!
|
||||||
|
|
||||||
|
// 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
|
||||||
|
} */
|
||||||
|
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
}
|
||||||
|
|
|
@ -32,28 +32,37 @@
|
||||||
|
|
||||||
namespace sgpem
|
namespace sgpem
|
||||||
{
|
{
|
||||||
|
class PythonPolicy;
|
||||||
|
class PythonPolicyManager;
|
||||||
|
|
||||||
class PythonPolicy;
|
class SG_DLLEXPORT PythonPolicy : public Policy
|
||||||
class PythonPolicyManager;
|
{
|
||||||
|
public:
|
||||||
|
//only PythonPolicyManager can create a PythonPolicy object
|
||||||
|
friend class PythonPolicyManager;
|
||||||
|
|
||||||
class SG_DLLEXPORT PythonPolicy : public Policy
|
virtual ~PythonPolicy();
|
||||||
{
|
|
||||||
public:
|
|
||||||
//only PythonPolicyManager can create a PythonPolicy object
|
|
||||||
friend class PythonPolicyManager;
|
|
||||||
|
|
||||||
void configure() {}
|
void configure();
|
||||||
void sort_queue(sgpem::Scheduler::event) const {}
|
void sort_queue(Scheduler::event) const;
|
||||||
Glib::ustring get_description() const {}
|
Glib::ustring get_description() const;
|
||||||
bool is_pre_emptive() const {}
|
bool is_pre_emptive() const;
|
||||||
int get_time_slice() const {}
|
int get_time_slice() const;
|
||||||
void set_time_slice(const int&) {}
|
void set_time_slice(const int&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PythonPolicy();
|
PythonPolicy(const char* name);
|
||||||
PythonPolicy(const PythonPolicy&);
|
PythonPolicy(const PythonPolicy&);
|
||||||
PythonPolicy& operator=(const PythonPolicy&);
|
PythonPolicy& operator=(const PythonPolicy&);
|
||||||
};
|
|
||||||
|
void wait_unlock() const;
|
||||||
|
|
||||||
|
PyObject* _adapter;
|
||||||
|
PyObject* _adapter_dict;
|
||||||
|
PyObject* _lock;
|
||||||
|
|
||||||
|
Glib::ustring _name;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,50 +76,7 @@ PythonPolicyManager::init()
|
||||||
|
|
||||||
// FIXME : Hardcoded policy name
|
// FIXME : Hardcoded policy name
|
||||||
char* policy_name = "fcfs";
|
char* policy_name = "fcfs";
|
||||||
PyObject* pLoadmeStr = PyString_FromString(policy_name);
|
PythonPolicy policy(policy_name);
|
||||||
PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr);
|
policy.configure();
|
||||||
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);
|
|
||||||
PyObject* pScriptAdapterDict = PyModule_GetDict(pScriptAdapterModule);
|
|
||||||
assert(pScriptAdapterDict);
|
|
||||||
|
|
||||||
// Now takes the user-defined policy class from pUserPolicyDict
|
|
||||||
PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, policy_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(pScriptAdapterDict, "ScriptAdapter");
|
|
||||||
PyObject* pAdapterCtorParam = PyTuple_New(1);
|
|
||||||
Py_INCREF(pPolicyClass); // PyTuple_SetItem steals a reference
|
|
||||||
PyTuple_SetItem(pAdapterCtorParam, 0, pPolicyClass);
|
|
||||||
PyObject* pAdapterObject = PyInstance_New(pAdapterClass, pAdapterCtorParam, NULL);
|
|
||||||
|
|
||||||
// try code
|
|
||||||
PyObject_CallMethod(pAdapterObject, "async_configure", NULL);
|
|
||||||
|
|
||||||
PyThreadState *_save;
|
|
||||||
Py_UNBLOCK_THREADS
|
|
||||||
sleep(5); // hack'a'ton! magggggiccc nummmbeeerrrrrs!!
|
|
||||||
|
|
||||||
Py_BLOCK_THREADS
|
|
||||||
|
|
||||||
// And now, who's your daddy, huh?
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ class fcfs(Policy) :
|
||||||
def is_preemptive(self):
|
def is_preemptive(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_time_sliced(self):
|
def get_time_slice(self):
|
||||||
return False
|
return -1
|
||||||
|
|
||||||
def sort_queue(self, event, queue):
|
def sort_queue(self, event, queue):
|
||||||
# How am I supposed to sort that mess??
|
# How am I supposed to sort that mess??
|
||||||
|
|
Loading…
Reference in New Issue