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