Panda3D
 All Classes Functions Variables Enumerations
asyncTaskSequence.cxx
00001 // Filename: asyncTaskSequence.cxx
00002 // Created by:  drose (04Oct08)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "asyncTaskSequence.h"
00016 
00017 TypeHandle AsyncTaskSequence::_type_handle;
00018 
00019 ////////////////////////////////////////////////////////////////////
00020 //     Function: AsyncTaskSequence::Constructor
00021 //       Access: Published
00022 //  Description:
00023 ////////////////////////////////////////////////////////////////////
00024 AsyncTaskSequence::
00025 AsyncTaskSequence(const string &name) :
00026   AsyncTask(name),
00027   _repeat_count(0),
00028   _task_index(0)
00029 {
00030 }
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: AsyncTaskSequence::Destructor
00034 //       Access: Published, Virtual
00035 //  Description:
00036 ////////////////////////////////////////////////////////////////////
00037 AsyncTaskSequence::
00038 ~AsyncTaskSequence() {
00039   set_current_task(NULL, true);
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: AsyncTaskSequence::is_runnable
00044 //       Access: Protected, Virtual
00045 //  Description: Override this function to return true if the task can
00046 //               be successfully executed, false if it cannot.  Mainly
00047 //               intended as a sanity check when attempting to add the
00048 //               task to a task manager.
00049 //
00050 //               This function is called with the lock held.
00051 ////////////////////////////////////////////////////////////////////
00052 bool AsyncTaskSequence::
00053 is_runnable() {
00054   return (get_num_tasks() > 0);
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: AsyncTaskSequence::do_task
00059 //       Access: Protected, Virtual
00060 //  Description: Override this function to do something useful for the
00061 //               task.
00062 //
00063 //               This function is called with the lock *not* held.
00064 ////////////////////////////////////////////////////////////////////
00065 AsyncTask::DoneStatus AsyncTaskSequence::
00066 do_task() {
00067   // Clear the delay that might have been set from a previous wait.
00068   _delay = 0.0;
00069   _has_delay = false;
00070 
00071   if (_task_index >= get_num_tasks()) {
00072     // Ran off the end of the task list.
00073     set_current_task(NULL, true);
00074     _task_index = 0;
00075     if (_task_index >= get_num_tasks()) {
00076       return DS_done;
00077     }
00078     if (_repeat_count > 0) {
00079       --_repeat_count;
00080     }
00081     if (_repeat_count != 0) {
00082       return DS_cont;
00083     }
00084     return DS_done;
00085   }
00086 
00087   AsyncTask *task = get_task(_task_index);
00088   set_current_task(task, true);
00089   nassertr(_current_task != (AsyncTask *)NULL, DS_exit);
00090 
00091   DoneStatus result = _current_task->do_task();
00092   switch (result) {
00093   case DS_again:
00094   case DS_pause:
00095     // The task wants to sleep for a period of time.
00096     {
00097       double now = _manager->_clock->get_frame_time();
00098       _current_task->_start_time = now + _current_task->_delay;
00099       
00100       _delay = _current_task->_delay;
00101       _has_delay = _current_task->_has_delay;
00102 
00103       if (result == DS_pause) {
00104         // When it wakes up, move on to the next task.
00105         ++_task_index;
00106       }
00107     }
00108     return DS_again;
00109 
00110   case DS_done:
00111     // Go on to the next task.
00112     ++_task_index;
00113     return DS_cont;
00114 
00115   case DS_cont:
00116   case DS_pickup:
00117   case DS_exit:
00118   case DS_interrupt:
00119     // Just return these results through.
00120     return result;
00121   }
00122 
00123   // Shouldn't get here.
00124   nassertr(false, DS_exit);
00125   return DS_exit;
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: AsyncTaskSequence::upon_birth
00130 //       Access: Protected, Virtual
00131 //  Description: Override this function to do something useful when the
00132 //               task has been added to the active queue.
00133 //
00134 //               This function is called with the lock held.  You may
00135 //               temporarily release if it necessary, but be sure to
00136 //               return with it held.
00137 ////////////////////////////////////////////////////////////////////
00138 void AsyncTaskSequence::
00139 upon_birth(AsyncTaskManager *manager) {
00140   AsyncTask::upon_birth(manager);
00141   _task_index = 0;
00142   set_current_task(NULL, true);
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: AsyncTaskSequence::upon_death
00147 //       Access: Protected, Virtual
00148 //  Description: Override this function to do something useful when the
00149 //               task has been removed from the active queue.  The
00150 //               parameter clean_exit is true if the task has been
00151 //               removed because it exited normally (returning
00152 //               DS_done), or false if it was removed for some other
00153 //               reason (e.g. AsyncTaskManager::remove()).  By the
00154 //               time this method is called, _manager has been
00155 //               cleared, so the parameter manager indicates the
00156 //               original AsyncTaskManager that owned this task.
00157 //
00158 //               The normal behavior is to throw the done_event only
00159 //               if clean_exit is true.
00160 //
00161 //               This function is called with the lock held.  You may
00162 //               temporarily release if it necessary, but be sure to
00163 //               return with it held.
00164 ////////////////////////////////////////////////////////////////////
00165 void AsyncTaskSequence::
00166 upon_death(AsyncTaskManager *manager, bool clean_exit) {
00167   AsyncTask::upon_death(manager, clean_exit);
00168   set_current_task(NULL, clean_exit);
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////
00172 //     Function: AsyncTaskSequence::set_current_task
00173 //       Access: Private
00174 //  Description: Sets the current executing task.  If NULL, sets the
00175 //               current task to NULL.
00176 ////////////////////////////////////////////////////////////////////
00177 void AsyncTaskSequence::
00178 set_current_task(AsyncTask *task, bool clean_exit) {
00179   if (_current_task == task) {
00180     return;
00181   }
00182 
00183   if (_current_task != (AsyncTask *)NULL) {
00184     nassertv(_current_task->_state == S_active_nested);
00185     nassertv(_current_task->_manager == _manager || _manager == NULL);
00186     _current_task->_state = S_inactive;
00187     _current_task->_manager = NULL;
00188     _current_task->upon_death(_manager, clean_exit);
00189   }
00190 
00191   _current_task = task;
00192 
00193   if (_current_task != (AsyncTask *)NULL) {
00194     nassertv(_current_task->_state == S_inactive);
00195     nassertv(_current_task->_manager == NULL);
00196     _current_task->upon_birth(_manager);
00197     nassertv(_current_task->_state == S_inactive);
00198     nassertv(_current_task->_manager == NULL);
00199     _current_task->_manager = _manager;
00200     _current_task->_state = S_active_nested;
00201 
00202     double now = _manager->_clock->get_frame_time();
00203     task->_start_time = now;
00204     task->_start_frame = _manager->_clock->get_frame_count();
00205   }
00206 }
 All Classes Functions Variables Enumerations