Panda3D
 All Classes Functions Variables Enumerations
asyncTaskSequence.cxx
1 // Filename: asyncTaskSequence.cxx
2 // Created by: drose (04Oct08)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "asyncTaskSequence.h"
16 #include "asyncTaskManager.h"
17 
18 TypeHandle AsyncTaskSequence::_type_handle;
19 
20 ////////////////////////////////////////////////////////////////////
21 // Function: AsyncTaskSequence::Constructor
22 // Access: Published
23 // Description:
24 ////////////////////////////////////////////////////////////////////
25 AsyncTaskSequence::
26 AsyncTaskSequence(const string &name) :
27  AsyncTask(name),
28  _repeat_count(0),
29  _task_index(0)
30 {
31 }
32 
33 ////////////////////////////////////////////////////////////////////
34 // Function: AsyncTaskSequence::Destructor
35 // Access: Published, Virtual
36 // Description:
37 ////////////////////////////////////////////////////////////////////
38 AsyncTaskSequence::
39 ~AsyncTaskSequence() {
40  set_current_task(NULL, true);
41 }
42 
43 ////////////////////////////////////////////////////////////////////
44 // Function: AsyncTaskSequence::is_runnable
45 // Access: Protected, Virtual
46 // Description: Override this function to return true if the task can
47 // be successfully executed, false if it cannot. Mainly
48 // intended as a sanity check when attempting to add the
49 // task to a task manager.
50 //
51 // This function is called with the lock held.
52 ////////////////////////////////////////////////////////////////////
53 bool AsyncTaskSequence::
54 is_runnable() {
55  return (get_num_tasks() > 0);
56 }
57 
58 ////////////////////////////////////////////////////////////////////
59 // Function: AsyncTaskSequence::do_task
60 // Access: Protected, Virtual
61 // Description: Override this function to do something useful for the
62 // task.
63 //
64 // This function is called with the lock *not* held.
65 ////////////////////////////////////////////////////////////////////
66 AsyncTask::DoneStatus AsyncTaskSequence::
67 do_task() {
68  // Clear the delay that might have been set from a previous wait.
69  _delay = 0.0;
70  _has_delay = false;
71 
72  if (_task_index >= get_num_tasks()) {
73  // Ran off the end of the task list.
74  set_current_task(NULL, true);
75  _task_index = 0;
76  if (_task_index >= get_num_tasks()) {
77  return DS_done;
78  }
79  if (_repeat_count > 0) {
80  --_repeat_count;
81  }
82  if (_repeat_count != 0) {
83  return DS_cont;
84  }
85  return DS_done;
86  }
87 
88  AsyncTask *task = get_task(_task_index);
89  set_current_task(task, true);
90  nassertr(_current_task != (AsyncTask *)NULL, DS_exit);
91 
92  DoneStatus result = _current_task->do_task();
93  switch (result) {
94  case DS_again:
95  case DS_pause:
96  // The task wants to sleep for a period of time.
97  {
98  double now = _manager->_clock->get_frame_time();
99  _current_task->_start_time = now + _current_task->_delay;
100 
101  _delay = _current_task->_delay;
102  _has_delay = _current_task->_has_delay;
103 
104  if (result == DS_pause) {
105  // When it wakes up, move on to the next task.
106  ++_task_index;
107  }
108  }
109  return DS_again;
110 
111  case DS_done:
112  // Go on to the next task.
113  ++_task_index;
114  return DS_cont;
115 
116  case DS_cont:
117  case DS_pickup:
118  case DS_exit:
119  case DS_interrupt:
120  // Just return these results through.
121  return result;
122  }
123 
124  // Shouldn't get here.
125  nassertr(false, DS_exit);
126  return DS_exit;
127 }
128 
129 ////////////////////////////////////////////////////////////////////
130 // Function: AsyncTaskSequence::upon_birth
131 // Access: Protected, Virtual
132 // Description: Override this function to do something useful when the
133 // task has been added to the active queue.
134 //
135 // This function is called with the lock held. You may
136 // temporarily release if it necessary, but be sure to
137 // return with it held.
138 ////////////////////////////////////////////////////////////////////
139 void AsyncTaskSequence::
140 upon_birth(AsyncTaskManager *manager) {
141  AsyncTask::upon_birth(manager);
142  _task_index = 0;
143  set_current_task(NULL, true);
144 }
145 
146 ////////////////////////////////////////////////////////////////////
147 // Function: AsyncTaskSequence::upon_death
148 // Access: Protected, Virtual
149 // Description: Override this function to do something useful when the
150 // task has been removed from the active queue. The
151 // parameter clean_exit is true if the task has been
152 // removed because it exited normally (returning
153 // DS_done), or false if it was removed for some other
154 // reason (e.g. AsyncTaskManager::remove()). By the
155 // time this method is called, _manager has been
156 // cleared, so the parameter manager indicates the
157 // original AsyncTaskManager that owned this task.
158 //
159 // The normal behavior is to throw the done_event only
160 // if clean_exit is true.
161 //
162 // This function is called with the lock held. You may
163 // temporarily release if it necessary, but be sure to
164 // return with it held.
165 ////////////////////////////////////////////////////////////////////
166 void AsyncTaskSequence::
167 upon_death(AsyncTaskManager *manager, bool clean_exit) {
168  AsyncTask::upon_death(manager, clean_exit);
169  set_current_task(NULL, clean_exit);
170 }
171 
172 ////////////////////////////////////////////////////////////////////
173 // Function: AsyncTaskSequence::set_current_task
174 // Access: Private
175 // Description: Sets the current executing task. If NULL, sets the
176 // current task to NULL.
177 ////////////////////////////////////////////////////////////////////
178 void AsyncTaskSequence::
179 set_current_task(AsyncTask *task, bool clean_exit) {
180  if (_current_task == task) {
181  return;
182  }
183 
184  if (_current_task != (AsyncTask *)NULL) {
185  nassertv(_current_task->_state == S_active_nested);
186  nassertv(_current_task->_manager == _manager || _manager == NULL);
187  _current_task->_state = S_inactive;
188  _current_task->_manager = NULL;
189  _current_task->upon_death(_manager, clean_exit);
190  }
191 
192  _current_task = task;
193 
194  if (_current_task != (AsyncTask *)NULL) {
195  nassertv(_current_task->_state == S_inactive);
196  nassertv(_current_task->_manager == NULL);
197  _current_task->upon_birth(_manager);
198  nassertv(_current_task->_state == S_inactive);
199  nassertv(_current_task->_manager == NULL);
200  _current_task->_manager = _manager;
201  _current_task->_state = S_active_nested;
202 
203  double now = _manager->_clock->get_frame_time();
204  task->_start_time = now;
205  task->_start_frame = _manager->_clock->get_frame_count();
206  }
207 }
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
int get_num_tasks() const
Returns the number of AsyncTasks in the collection.
AsyncTask * get_task(int index) const
Returns the nth AsyncTask in the collection.
This class represents a concrete task performed by an AsyncManager.
Definition: asyncTask.h:43
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85