interrupt should not stop task

This commit is contained in:
David Rose 2008-10-10 21:30:11 +00:00
parent 7f9a509f04
commit bca1533952
7 changed files with 33 additions and 30 deletions

View File

@ -424,8 +424,9 @@ is_runnable() {
// DS_pause: delay the task for set_delay() seconds, // DS_pause: delay the task for set_delay() seconds,
// then stop it. This is only useful within a sequence. // then stop it. This is only useful within a sequence.
// //
// DS_abort: stop the task, and interrupt the whole // DS_interrupt: Interrupt the whole AsyncTaskManager.
// AsyncTaskManager. // The task will continue again next epoch, as if it had
// returned DS_cont.
// //
// This function is called with the lock *not* held. // This function is called with the lock *not* held.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -50,13 +50,13 @@ PUBLISHED:
virtual ~AsyncTask(); virtual ~AsyncTask();
enum DoneStatus { enum DoneStatus {
DS_done, // normal task completion DS_done, // normal task completion
DS_cont, // run task again next epoch DS_cont, // run task again next epoch
DS_again, // start the task over from the beginning DS_again, // start the task over from the beginning
DS_pickup, // run task again this frame, if frame budget allows DS_pickup, // run task again this frame, if frame budget allows
DS_exit, // stop the enclosing sequence DS_exit, // stop the enclosing sequence
DS_pause, // pause, then exit (useful within a sequence) DS_pause, // pause, then exit (useful within a sequence)
DS_abort, // interrupt the task manager DS_interrupt, // interrupt the task manager, but run task again
}; };
enum State { enum State {

View File

@ -264,7 +264,7 @@ get_timeslice_priority() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void AsyncTaskChain:: void AsyncTaskChain::
stop_threads() { stop_threads() {
if (_state == S_started || _state == S_aborting) { if (_state == S_started || _state == S_interrupted) {
// Clean up all of the threads. // Clean up all of the threads.
MutexHolder holder(_manager->_lock); MutexHolder holder(_manager->_lock);
do_stop_threads(); do_stop_threads();
@ -280,7 +280,7 @@ stop_threads() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void AsyncTaskChain:: void AsyncTaskChain::
start_threads() { start_threads() {
if (_state == S_initial || _state == S_aborting) { if (_state == S_initial || _state == S_interrupted) {
MutexHolder holder(_manager->_lock); MutexHolder holder(_manager->_lock);
do_start_threads(); do_start_threads();
} }
@ -563,7 +563,7 @@ do_wait_for_tasks() {
if (_threads.empty()) { if (_threads.empty()) {
// Non-threaded case. // Non-threaded case.
while (_num_tasks > 0) { while (_num_tasks > 0) {
if (_state == S_shutdown || _state == S_aborting) { if (_state == S_shutdown || _state == S_interrupted) {
return; return;
} }
do_poll(); do_poll();
@ -572,7 +572,7 @@ do_wait_for_tasks() {
} else { } else {
// Threaded case. // Threaded case.
while (_num_tasks > 0) { while (_num_tasks > 0) {
if (_state == S_shutdown || _state == S_aborting) { if (_state == S_shutdown || _state == S_interrupted) {
return; return;
} }
@ -746,14 +746,16 @@ service_one_task(AsyncTaskChain::AsyncTaskChainThread *thread) {
_cvar.signal_all(); _cvar.signal_all();
break; break;
case AsyncTask::DS_abort: case AsyncTask::DS_interrupt:
// The task had an exception and wants to raise a big flag. // The task had an exception and wants to raise a big flag.
cleanup_task(task, true, false); task->_state = AsyncTask::S_active;
_next_active.push_back(task);
if (_state == S_started) { if (_state == S_started) {
_state = S_aborting; _state = S_interrupted;
_cvar.signal_all(); _cvar.signal_all();
} }
break; break;
default: default:
// The task has finished. // The task has finished.
@ -1019,7 +1021,7 @@ filter_timeslice_priority() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void AsyncTaskChain:: void AsyncTaskChain::
do_stop_threads() { do_stop_threads() {
if (_state == S_started || _state == S_aborting) { if (_state == S_started || _state == S_interrupted) {
if (task_cat.is_debug() && !_threads.empty()) { if (task_cat.is_debug() && !_threads.empty()) {
task_cat.debug() task_cat.debug()
<< "Stopping " << _threads.size() << "Stopping " << _threads.size()
@ -1062,7 +1064,7 @@ do_stop_threads() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void AsyncTaskChain:: void AsyncTaskChain::
do_start_threads() { do_start_threads() {
if (_state == S_aborting) { if (_state == S_interrupted) {
do_stop_threads(); do_stop_threads();
} }
@ -1166,7 +1168,7 @@ do_poll() {
do { do {
while (!_active.empty()) { while (!_active.empty()) {
if (_state == S_shutdown || _state == S_aborting) { if (_state == S_shutdown || _state == S_interrupted) {
return; return;
} }
int frame = _manager->_clock->get_frame_count(); int frame = _manager->_clock->get_frame_count();
@ -1405,7 +1407,7 @@ AsyncTaskChainThread(const string &name, AsyncTaskChain *chain) :
void AsyncTaskChain::AsyncTaskChainThread:: void AsyncTaskChain::AsyncTaskChainThread::
thread_main() { thread_main() {
MutexHolder holder(_chain->_manager->_lock); MutexHolder holder(_chain->_manager->_lock);
while (_chain->_state != S_shutdown && _chain->_state != S_aborting) { while (_chain->_state != S_shutdown && _chain->_state != S_interrupted) {
thread_consider_yield(); thread_consider_yield();
if (!_chain->_active.empty() && if (!_chain->_active.empty() &&
_chain->_active.front()->get_sort() == _chain->_current_sort) { _chain->_active.front()->get_sort() == _chain->_current_sort) {
@ -1420,7 +1422,7 @@ thread_main() {
// frame. // frame.
if (_chain->_frame_budget >= 0.0 && _chain->_time_in_frame >= _chain->_frame_budget) { 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 && while (_chain->_frame_budget >= 0.0 && _chain->_time_in_frame >= _chain->_frame_budget &&
_chain->_state != S_shutdown && _chain->_state != S_aborting) { _chain->_state != S_shutdown && _chain->_state != S_interrupted) {
_chain->cleanup_pickup_mode(); _chain->cleanup_pickup_mode();
_chain->_manager->_frame_cvar.wait(); _chain->_manager->_frame_cvar.wait();
frame = _chain->_manager->_clock->get_frame_count(); frame = _chain->_manager->_clock->get_frame_count();

View File

@ -160,10 +160,10 @@ protected:
ConditionVarFull _cvar; // signaled when one of the task heaps, _state, or _current_sort changes, or a task finishes. ConditionVarFull _cvar; // signaled when one of the task heaps, _state, or _current_sort changes, or a task finishes.
enum State { enum State {
S_initial, // no threads yet S_initial, // no threads yet
S_started, // threads have been started S_started, // threads have been started
S_aborting, // task returned DS_abort, shutdown requested from sub-thread. S_interrupted, // task returned DS_interrupt, requested from sub-thread.
S_shutdown // waiting for thread shutdown, requested from main thread S_shutdown // waiting for thread shutdown, requested from main thread
}; };
bool _tick_clock; bool _tick_clock;

View File

@ -115,7 +115,7 @@ do_task() {
case DS_cont: case DS_cont:
case DS_pickup: case DS_pickup:
case DS_exit: case DS_exit:
case DS_abort: case DS_interrupt:
// Just return these results through. // Just return these results through.
return result; return result;
} }

View File

@ -72,7 +72,7 @@ is_runnable() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
AsyncTask::DoneStatus GenericAsyncTask:: AsyncTask::DoneStatus GenericAsyncTask::
do_task() { do_task() {
nassertr(_function != NULL, DS_abort); nassertr(_function != NULL, DS_interrupt);
return (*_function)(this, _user_data); return (*_function)(this, _user_data);
} }

View File

@ -400,7 +400,7 @@ do_python_task() {
if (_generator != (PyObject *)NULL) { if (_generator != (PyObject *)NULL) {
// We are calling a generator. // We are calling a generator.
PyObject *func = PyObject_GetAttrString(_generator, "next"); PyObject *func = PyObject_GetAttrString(_generator, "next");
nassertr(func != (PyObject *)NULL, DS_abort); nassertr(func != (PyObject *)NULL, DS_interrupt);
result = PyObject_CallObject(func, NULL); result = PyObject_CallObject(func, NULL);
Py_DECREF(func); Py_DECREF(func);
@ -418,7 +418,7 @@ do_python_task() {
if (result == (PyObject *)NULL) { if (result == (PyObject *)NULL) {
task_cat.error() task_cat.error()
<< "Exception occurred in " << *this << "\n"; << "Exception occurred in " << *this << "\n";
return DS_abort; return DS_interrupt;
} }
if (result == Py_None) { if (result == Py_None) {
@ -463,7 +463,7 @@ do_python_task() {
string message = strm.str(); string message = strm.str();
nassert_raise(message); nassert_raise(message);
return DS_abort; return DS_interrupt;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////