- 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:
parent
50a5214bb9
commit
3b593e00ae
|
@ -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
|
||||||
#
|
#
|
||||||
|
@ -28,7 +21,13 @@ 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()
|
||||||
|
|
|
@ -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,24 +167,24 @@ 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);
|
||||||
|
|
||||||
//Py_UNBLOCK_THREADS;
|
//Py_UNBLOCK_THREADS;
|
||||||
|
|
||||||
throw UserInterruptException("User-defined policy is "
|
throw UserInterruptException("User-defined policy is "
|
||||||
"taking too long to terminate.");
|
"taking too long to terminate.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
|
@ -82,7 +82,6 @@ namespace sgpem
|
||||||
|
|
||||||
PyObject* _adapter;
|
PyObject* _adapter;
|
||||||
PyObject* _adapter_dict;
|
PyObject* _adapter_dict;
|
||||||
PyObject* _lock;
|
|
||||||
|
|
||||||
Glib::ustring _name;
|
Glib::ustring _name;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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: \
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue