fix some threading issues
This commit is contained in:
parent
8bb89607ab
commit
a29328046a
|
|
@ -1373,14 +1373,18 @@ thread_main() {
|
|||
|
||||
// If we've exceeded our frame budget, sleep until the next
|
||||
// frame.
|
||||
while (_chain->_frame_budget >= 0.0 && _chain->_time_in_frame >= _chain->_frame_budget) {
|
||||
_chain->cleanup_pickup_mode();
|
||||
_chain->_manager->_frame_cvar.wait();
|
||||
frame = _chain->_manager->_clock->get_frame_count();
|
||||
if (_chain->_current_frame != frame) {
|
||||
_chain->_current_frame = frame;
|
||||
_chain->_time_in_frame = 0.0;
|
||||
if (_chain->_frame_budget >= 0.0 && _chain->_time_in_frame >= _chain->_frame_budget) {
|
||||
while (_chain->_frame_budget >= 0.0 && _chain->_time_in_frame >= _chain->_frame_budget) {
|
||||
_chain->cleanup_pickup_mode();
|
||||
_chain->_manager->_frame_cvar.wait();
|
||||
frame = _chain->_manager->_clock->get_frame_count();
|
||||
if (_chain->_current_frame != frame) {
|
||||
_chain->_current_frame = frame;
|
||||
_chain->_time_in_frame = 0.0;
|
||||
}
|
||||
}
|
||||
// Now that it's the next frame, go back to the top of the loop.
|
||||
continue;
|
||||
}
|
||||
|
||||
PStatTimer timer(_task_pcollector);
|
||||
|
|
|
|||
|
|
@ -313,6 +313,30 @@ __getattr__(const string &attr_name) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
AsyncTask::DoneStatus PythonTask::
|
||||
do_task() {
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
// Use PyGILState to protect this asynchronous call.
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
#endif
|
||||
|
||||
DoneStatus result = do_python_task();
|
||||
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PythonTask::do_python_task
|
||||
// Access: Protected
|
||||
// Description: The Python calls that implement do_task(). This
|
||||
// function is separate so we can acquire the Python
|
||||
// interpretor lock while it runs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AsyncTask::DoneStatus PythonTask::
|
||||
do_python_task() {
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (_generator == (PyObject *)NULL) {
|
||||
|
|
@ -419,7 +443,18 @@ do_task() {
|
|||
void PythonTask::
|
||||
upon_birth() {
|
||||
AsyncTask::upon_birth();
|
||||
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
// Use PyGILState to protect this asynchronous call.
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
#endif
|
||||
|
||||
call_owner_method("_addTask");
|
||||
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -442,8 +477,19 @@ upon_birth() {
|
|||
void PythonTask::
|
||||
upon_death(bool clean_exit) {
|
||||
AsyncTask::upon_death(clean_exit);
|
||||
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
// Use PyGILState to protect this asynchronous call.
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
#endif
|
||||
|
||||
call_owner_method("_clearTask");
|
||||
call_function(_upon_death);
|
||||
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ PUBLISHED:
|
|||
|
||||
protected:
|
||||
virtual DoneStatus do_task();
|
||||
DoneStatus do_python_task();
|
||||
virtual void upon_birth();
|
||||
virtual void upon_death(bool clean_exit);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ wait(double timeout) {
|
|||
|
||||
int seconds = (int)floor(timeout);
|
||||
ts.tv_sec += seconds;
|
||||
ts.tv_nsec += (timeout - seconds) * 1000000.0;
|
||||
ts.tv_nsec += (int)((timeout - seconds) * 1000000.0);
|
||||
|
||||
int result = pthread_cond_timedwait(&_cvar, &_mutex._lock, &ts);
|
||||
nassertv(result == 0);
|
||||
|
|
|
|||
|
|
@ -50,12 +50,6 @@ PythonThread(PyObject *function, PyObject *args,
|
|||
nassert_raise("Invalid args passed to PythonThread constructor");
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SIMPLE_THREADS
|
||||
// Ensure that the Python threading system is initialized and ready
|
||||
// to go.
|
||||
PyEval_InitThreads();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -13,40 +13,6 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::Constructor
|
||||
// Access: Protected
|
||||
// Description: Creates a new Thread object, but does not
|
||||
// immediately start executing it. This gives the
|
||||
// caller a chance to store it in a PT(Thread) object,
|
||||
// if desired, before the thread gets a chance to
|
||||
// terminate and destruct itself.
|
||||
//
|
||||
// Call start() to begin thread execution.
|
||||
//
|
||||
// The name should be unique for each thread (though
|
||||
// this is not enforced, and not strictly required).
|
||||
// The sync_name can be shared between multiple
|
||||
// different threads; threads that run synchronously
|
||||
// with each other should be given the same sync_name,
|
||||
// for the benefit of PStats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread::
|
||||
Thread(const string &name, const string &sync_name) :
|
||||
_name(name),
|
||||
_sync_name(sync_name),
|
||||
_impl(this)
|
||||
{
|
||||
_started = false;
|
||||
_pstats_index = -1;
|
||||
_pstats_callback = NULL;
|
||||
_pipeline_stage = 0;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
_blocked_on_mutex = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::Copy Constructor
|
||||
// Access: Private
|
||||
|
|
|
|||
|
|
@ -21,6 +21,46 @@ Thread *Thread::_main_thread;
|
|||
Thread *Thread::_external_thread;
|
||||
TypeHandle Thread::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::Constructor
|
||||
// Access: Protected
|
||||
// Description: Creates a new Thread object, but does not
|
||||
// immediately start executing it. This gives the
|
||||
// caller a chance to store it in a PT(Thread) object,
|
||||
// if desired, before the thread gets a chance to
|
||||
// terminate and destruct itself.
|
||||
//
|
||||
// Call start() to begin thread execution.
|
||||
//
|
||||
// The name should be unique for each thread (though
|
||||
// this is not enforced, and not strictly required).
|
||||
// The sync_name can be shared between multiple
|
||||
// different threads; threads that run synchronously
|
||||
// with each other should be given the same sync_name,
|
||||
// for the benefit of PStats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Thread::
|
||||
Thread(const string &name, const string &sync_name) :
|
||||
_name(name),
|
||||
_sync_name(sync_name),
|
||||
_impl(this)
|
||||
{
|
||||
_started = false;
|
||||
_pstats_index = -1;
|
||||
_pstats_callback = NULL;
|
||||
_pipeline_stage = 0;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
_blocked_on_mutex = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PYTHON) && !defined(SIMPLE_THREADS)
|
||||
// Ensure that the Python threading system is initialized and ready
|
||||
// to go.
|
||||
PyEval_InitThreads();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::Destructor
|
||||
// Access: Published, Virtual
|
||||
|
|
@ -239,7 +279,7 @@ call_python_func(PyObject *function, PyObject *args) {
|
|||
}
|
||||
|
||||
#else // SIMPLE_THREADS
|
||||
// With true threading enabled, we're better off using PyGILSTate.
|
||||
// With true threading enabled, we're better off using PyGILState.
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class MutexDebug;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PIPELINE Thread : public TypedReferenceCount {
|
||||
protected:
|
||||
INLINE Thread(const string &name, const string &sync_name);
|
||||
Thread(const string &name, const string &sync_name);
|
||||
|
||||
PUBLISHED:
|
||||
virtual ~Thread();
|
||||
|
|
|
|||
Loading…
Reference in New Issue