- 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:
tchernobog 2006-02-22 15:16:08 +00:00
parent 882a6acf5e
commit 8f655f2f69
8 changed files with 211 additions and 96 deletions

View File

@ -50,6 +50,4 @@ namespace sgpem
}//~ namespace sgpem }//~ namespace sgpem
#endif
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -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: void configure();
//only PythonPolicyManager can create a PythonPolicy object void sort_queue(Scheduler::event) const;
friend class PythonPolicyManager; Glib::ustring get_description() const;
bool is_pre_emptive() const;
void configure() {} int get_time_slice() const;
void sort_queue(sgpem::Scheduler::event) const {} void set_time_slice(const int&);
Glib::ustring get_description() const {}
bool is_pre_emptive() const {} private:
int get_time_slice() const {} PythonPolicy(const char* name);
void set_time_slice(const int&) {} PythonPolicy(const PythonPolicy&);
PythonPolicy& operator=(const PythonPolicy&);
private:
PythonPolicy(); void wait_unlock() const;
PythonPolicy(const PythonPolicy&);
PythonPolicy& operator=(const PythonPolicy&); PyObject* _adapter;
}; PyObject* _adapter_dict;
PyObject* _lock;
Glib::ustring _name;
};
} }

View File

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

View File

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