Panda3D
Loading...
Searching...
No Matches
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
17TypeHandle AsyncTaskSequence::_type_handle;
18
19/**
20 *
21 */
22AsyncTaskSequence::
23AsyncTaskSequence(const std::string &name) :
24 AsyncTask(name),
25 _repeat_count(0),
26 _task_index(0)
27{
28}
29
30/**
31 *
32 */
33AsyncTaskSequence::
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 */
45bool AsyncTaskSequence::
46is_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 */
55AsyncTask::DoneStatus AsyncTaskSequence::
56do_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 */
126void AsyncTaskSequence::
127upon_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 */
147void AsyncTaskSequence::
148upon_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 */
156void AsyncTaskSequence::
157set_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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_num_tasks
Returns the number of AsyncTasks in the collection.
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