- Partial attempt at fixing PythonPolicies broken return values

git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@525 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
tchernobog 2006-03-10 14:54:24 +00:00
parent 50a5214bb9
commit 3b593e00ae
5 changed files with 54 additions and 44 deletions

View File

@ -1,13 +1,6 @@
import mutex, thread import mutex, thread
import sgpem import sgpem
## Var Global syncronization object
_g_mutex = mutex.mutex()
## @var 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 +22,12 @@ class ScriptAdapter :
## @var The event to pass to Policy.sort_queue() after the asynchronous call ## @var The event to pass to Policy.sort_queue() after the asynchronous call
_event = None _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 ## @brief Constructor of ScriptAdapter
# #
@ -43,7 +42,7 @@ class ScriptAdapter :
# #
# @param self The caller object # @param self The caller object
def async_configure(self): def async_configure(self):
_g_mutex.lock(ScriptAdapter._wrap_configure, self ) self._g_mutex.lock(ScriptAdapter._wrap_configure, self )
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,))
@ -51,7 +50,7 @@ class ScriptAdapter :
def _wrap_configure_callback(self): def _wrap_configure_callback(self):
# call configure method # call configure method
self._policy.configure() self._policy.configure()
_g_mutex.unlock() self._g_mutex.unlock()
## @brief Asynchronously call Policy.sort_queue() ## @brief Asynchronously call Policy.sort_queue()
@ -63,7 +62,7 @@ class ScriptAdapter :
# @param event The event to pass to sort_queue # @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) self._g_mutex.lock(ScriptAdapter._wrap_sort_queue, self)
def _wrap_sort_queue(self): def _wrap_sort_queue(self):
thread.start_new_thread(ScriptAdapter._wrap_sort_queue_callback, thread.start_new_thread(ScriptAdapter._wrap_sort_queue_callback,
@ -73,7 +72,7 @@ class ScriptAdapter :
# here we retrieve and pass the ready queue # here we retrieve and pass the ready queue
queue = sgpem.Scheduler.get_instance().get_ready_queue() queue = sgpem.Scheduler.get_instance().get_ready_queue()
self._policy.sort_queue(event, queue) self._policy.sort_queue(event, queue)
_g_mutex.unlock() self._g_mutex.unlock()
## @brief Asynchronously call Policy.is_preemptive() ## @brief Asynchronously call Policy.is_preemptive()
@ -86,19 +85,25 @@ class ScriptAdapter :
thread.start_new_thread(ScriptAdapter._wrap_is_preemptive_callback, (self,)) thread.start_new_thread(ScriptAdapter._wrap_is_preemptive_callback, (self,))
def _wrap_is_preemptive_callback(self): def _wrap_is_preemptive_callback(self):
_ret_val = self._policy.is_preemptive() self._ret_val = self._policy.is_preemptive()
_g_mutex.unlock() self._g_mutex.unlock()
## @brief Asynchronously call Policy.get_time_slice() ## @brief Asynchronously call Policy.get_time_slice()
# #
# @param self The caller object # @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) self._g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self)
def _wrap_get_time_slice(self): def _wrap_get_time_slice(self):
thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,)) thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,))
def _wrap_get_time_slice_callback(self): def _wrap_get_time_slice_callback(self):
_ret_val = self._policy.get_time_slice() self._ret_val = self._policy.get_time_slice()
_g_mutex.unlock() 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 test_lock(self):
return self._g_mutex.test()

View File

@ -31,8 +31,7 @@ using namespace std;
// *strong* exception checking / handling! // *strong* exception checking / handling!
PythonPolicy::PythonPolicy(const char* name) PythonPolicy::PythonPolicy(const char* name)
: _adapter(NULL), _adapter_dict(NULL), : _adapter(NULL), _adapter_dict(NULL), _name(name)
_lock(NULL), _name(name)
{ {
PyObject* pLoadmeStr = PyString_FromString(name); PyObject* pLoadmeStr = PyString_FromString(name);
PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr); PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr);
@ -56,18 +55,13 @@ PythonPolicy::PythonPolicy(const char* name)
assert(pScriptAdapterModule); assert(pScriptAdapterModule);
_adapter_dict = PyModule_GetDict(pScriptAdapterModule); _adapter_dict = PyModule_GetDict(pScriptAdapterModule);
assert(_adapter_dict); assert(_adapter_dict);
// We want to keep a reference to it even if we decref // We want to keep a reference to it
// its containing module
Py_INCREF(_adapter_dict); Py_INCREF(_adapter_dict);
// Now takes the user-defined policy class from pUserPolicyDict // Now takes the user-defined policy class from pUserPolicyDict
PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, name); PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, name);
assert(pPolicyClass); // FIXME needs stricter checking and exception throwing 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 : // Creates a new object of type ScriptAdapter :
// takes init function from ScriptAdapter class // takes init function from ScriptAdapter class
PyObject* pAdapterClass = PyDict_GetItemString(_adapter_dict, "ScriptAdapter"); PyObject* pAdapterClass = PyDict_GetItemString(_adapter_dict, "ScriptAdapter");
@ -136,8 +130,10 @@ PythonPolicy::is_pre_emptive() const throw(UserInterruptException)
wait_unlock(); wait_unlock();
// Parse return value stored in global Python object // Parse return value stored in global Python object
retval = PyDict_GetItemString(_adapter_dict, "_ret_val"); retval = PyObject_CallMethod(_adapter, "get_return_value", NULL);
return PyBool_Check(retval); bool ret = PyObject_IsTrue(retval);
Py_DECREF(retval);
return ret;
} }
@ -149,8 +145,10 @@ PythonPolicy::get_time_slice() const throw(UserInterruptException) {
wait_unlock(); wait_unlock();
// Parse return value stored in global Python object // Parse return value stored in global Python object
retval = PyDict_GetItemString(_adapter_dict, "_ret_val"); retval = PyObject_CallMethod(_adapter, "get_return_value", NULL);
long tmp = PyInt_AsLong(retval); long tmp = PyInt_AsLong(retval);
Py_DECREF(retval);
return tmp < 0 ? numeric_limits<int>::max() : static_cast<int>(tmp); return tmp < 0 ? numeric_limits<int>::max() : static_cast<int>(tmp);
} }
@ -169,11 +167,12 @@ PythonPolicy::wait_unlock() const throw(UserInterruptException)
usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!!
Py_BLOCK_THREADS; Py_BLOCK_THREADS;
PyObject* retval = PyObject_CallMethod(_lock, "test", NULL); PyObject* retval = PyObject_CallMethod(_adapter, "test_lock", NULL);
still_locked = PyBool_Check(retval); assert(retval);
still_locked = PyObject_IsTrue(retval);
Py_DECREF(retval); Py_DECREF(retval);
if(i++ > WAIT_FOR*12) if(i++ > 12) /* waits for WAIT_FOR * 12 microseconds == 3 secs */
{ {
PyThreadState_Clear(_save); PyThreadState_Clear(_save);
PyEval_RestoreThread(_save); PyEval_RestoreThread(_save);
@ -186,7 +185,6 @@ PythonPolicy::wait_unlock() const throw(UserInterruptException)
} }
while(still_locked); while(still_locked);
// What we should really do here: // What we should really do here:
/* do { /* do {
enable python threads enable python threads

View File

@ -82,7 +82,6 @@ namespace sgpem
PyObject* _adapter; PyObject* _adapter;
PyObject* _adapter_dict; PyObject* _adapter_dict;
PyObject* _lock;
Glib::ustring _name; Glib::ustring _name;
}; };

View File

@ -33,7 +33,7 @@ class fcfs(Policy) :
return False return False
def get_time_slice(self): def get_time_slice(self):
return -1 return -2
def sort_queue(self, event, queue): def sort_queue(self, event, queue):
cmpf = lambda a, b: \ cmpf = lambda a, b: \

View File

@ -77,8 +77,17 @@ Simulation::run() throw(UserInterruptException)
{ {
History& h = History::get_instance(); History& h = History::get_instance();
if (_state == state_stopped) switch(_state)
h.truncate_at(0); {
case state_running:
// FIXME: write out something, or just ignore user input?
return;
case state_stopped:
h.truncate_at(0);
break;
default:
break;
}
_state = state_running; _state = state_running;
@ -86,7 +95,7 @@ Simulation::run() throw(UserInterruptException)
if (_mode) if (_mode)
{ {
loop: do {
// chech for termination // chech for termination
bool all_term = true; bool all_term = true;
smart_ptr<SchedulableList> left = h.get_simulation_status_at(h.get_current_time()); smart_ptr<SchedulableList> left = h.get_simulation_status_at(h.get_current_time());
@ -101,8 +110,8 @@ loop:
//by the last execution of upadate() //by the last execution of upadate()
if (all_term) if (all_term)
{ {
_state = state_paused; _state = state_stopped;
return; return; // Exit from loop
} }
try try
@ -116,16 +125,15 @@ loop:
} }
catch(UserInterruptException e) catch(UserInterruptException e)
{ {
stop(); stop();
throw;
throw;
} }
//check the state //check the state
if (_state == state_stopped || _state == state_paused) if (_state == state_stopped || _state == state_paused)
return; return;
goto loop; } while(true);
} }
//******* STEP by STEP //******* STEP by STEP