35AsyncTaskManager(
const string &name) :
37 _lock(
"AsyncTaskManager::_lock"),
43 do_make_task_chain(
"default");
62 if (task_cat.is_debug()) {
63 do_output(task_cat.debug());
70 while (!_task_chains.empty()) {
71 PT(AsyncTaskChain) chain = _task_chains[_task_chains.size() - 1];
72 _task_chains.pop_back();
78 if (_num_tasks == 1) {
79 nassertv(_tasks_by_name.size() == 1);
80 TasksByName::const_iterator tbni = _tasks_by_name.begin();
81 AsyncTask *task = (*tbni);
82 nassertv(task->_state == AsyncTask::S_servicing ||
83 task->_state == AsyncTask::S_servicing_removed);
84 task->_state = AsyncTask::S_servicing_removed;
89 nassertd(_num_tasks == 0 && _tasks_by_name.empty()) {
91 <<
"_num_tasks = " << _num_tasks <<
" _tasks_by_name = " << _tasks_by_name.size() <<
"\n";
92 TasksByName::const_iterator tbni;
93 for (tbni = _tasks_by_name.begin();
94 tbni != _tasks_by_name.end();
97 <<
" " << *(*tbni) <<
"\n";
110 return _task_chains.size();
118 MutexHolder holder(_lock);
119 nassertr(n >= 0 && n < (
int)_task_chains.size(),
nullptr);
120 return _task_chains[n];
131 return do_make_task_chain(name);
141 return do_find_task_chain(name);
154 PT(AsyncTaskChain) chain =
new AsyncTaskChain(
this, name);
155 TaskChains::iterator tci = _task_chains.find(chain);
156 if (tci == _task_chains.end()) {
163 while (chain->_num_tasks != 0) {
166 <<
"Waiting for tasks on chain " << name <<
" to finish.\n";
167 chain->do_wait_for_tasks();
172 _task_chains.erase(tci);
181add(AsyncTask *task) {
182 nassertv(task->is_runnable());
187 if (task_cat.is_debug()) {
189 <<
"Adding " << *task <<
"\n";
192 if (task->_state == AsyncTask::S_servicing_removed) {
193 if (task->_manager ==
this) {
196 task->_state = AsyncTask::S_servicing;
201 nassertv(task->_manager ==
nullptr &&
202 task->_state == AsyncTask::S_inactive);
203 nassertv(!do_has_task(task));
206 task->upon_birth(
this);
208 nassertv(task->_manager ==
nullptr &&
209 task->_state == AsyncTask::S_inactive);
210 nassertv(!do_has_task(task));
212 AsyncTaskChain *chain = do_find_task_chain(task->_chain_name);
213 if (chain ==
nullptr) {
215 <<
"Creating implicit AsyncTaskChain " << task->_chain_name
216 <<
" for " << get_type() <<
" " << get_name() <<
"\n";
217 chain = do_make_task_chain(task->_chain_name);
231 if (task->_manager !=
this) {
232 nassertr(!do_has_task(task),
false);
236 if (task->_state == AsyncTask::S_servicing_removed) {
254 AsyncTask sample_task(name);
257 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
258 if (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
270 AsyncTask sample_task(name);
273 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
275 while (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
290 AsyncTask sample_task(prefix);
293 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
295 while (tbni != _tasks_by_name.end() && (*tbni)->get_name().substr(0, prefix.size()) == prefix) {
296 AsyncTask *task = (*tbni);
297 if (pattern.
matches(task->get_name())) {
322 size_t num_removed = 0;
325 for (
size_t i = 0; i < num_tasks; ++i) {
326 PT(AsyncTask) task = tasks.
get_task(i);
328 if (task->_manager !=
this) {
330 nassertr(!do_has_task(task), num_removed);
332 nassertr(task->_chain->_manager ==
this, num_removed);
333 if (task_cat.is_debug()) {
335 <<
"Removing " << *task <<
"\n";
337 if (task->_chain->do_remove(task,
true)) {
340 if (task_cat.is_debug()) {
342 <<
" (unable to remove " << *task <<
")\n";
359 while (_num_tasks > 0) {
363 for (
unsigned int i = 0; i < _task_chains.size(); ++i) {
364 AsyncTaskChain *chain = _task_chains[i];
365 chain->do_wait_for_tasks();
382 for (
unsigned int i = 0; i < _task_chains.size(); ++i) {
383 AsyncTaskChain *chain = _task_chains[i];
384 chain->do_stop_threads();
400 for (
unsigned int i = 0; i < _task_chains.size(); ++i) {
401 AsyncTaskChain *chain = _task_chains[i];
403 chain->do_start_threads();
416 TaskChains::const_iterator tci;
417 for (tci = _task_chains.begin();
418 tci != _task_chains.end();
434 MutexHolder holder(_lock);
436 AsyncTaskCollection result;
437 TaskChains::const_iterator tci;
438 for (tci = _task_chains.begin();
439 tci != _task_chains.end();
441 AsyncTaskChain *chain = (*tci);
454 MutexHolder holder(_lock);
456 AsyncTaskCollection result;
457 TaskChains::const_iterator tci;
458 for (tci = _task_chains.begin();
459 tci != _task_chains.end();
461 AsyncTaskChain *chain = (*tci);
480 for (
unsigned int i = 0; i < _task_chains.size(); ++i) {
481 AsyncTaskChain *chain = _task_chains[i];
484 if (chain->_state == AsyncTaskChain::S_interrupted) {
493 _frame_cvar.notify_all();
505 bool got_any =
false;
506 double next_wake_time = -1.0;
508 TaskChains::const_iterator tci;
509 for (tci = _task_chains.begin();
510 tci != _task_chains.end();
513 double time = chain->do_get_next_wake_time();
517 next_wake_time = time;
519 next_wake_time = std::min(time, next_wake_time);
524 return next_wake_time;
530void AsyncTaskManager::
531output(std::ostream &out)
const {
532 MutexHolder holder(_lock);
539void AsyncTaskManager::
540write(std::ostream &out,
int indent_level)
const {
541 MutexHolder holder(_lock);
543 << get_type() <<
" " << get_name() <<
"\n";
545 TaskChains::const_iterator tci;
546 for (tci = _task_chains.begin();
547 tci != _task_chains.end();
549 AsyncTaskChain *chain = (*tci);
550 if (chain->_num_tasks != 0) {
552 chain->do_write(out, indent_level + 2);
565do_make_task_chain(
const string &name) {
566 PT(AsyncTaskChain) chain =
new AsyncTaskChain(
this, name);
568 TaskChains::const_iterator tci = _task_chains.insert(chain).first;
579do_find_task_chain(
const string &name) {
580 PT(AsyncTaskChain) chain =
new AsyncTaskChain(
this, name);
582 TaskChains::const_iterator tci = _task_chains.find(chain);
583 if (tci != _task_chains.end()) {
593void AsyncTaskManager::
595 if (!task->get_name().empty()) {
597 TasksByName::iterator tbni = _tasks_by_name.lower_bound(task);
598 while (tbni != _tasks_by_name.end()) {
599 if ((*tbni) == task) {
600 _tasks_by_name.erase(tbni);
603 if ((*tbni)->get_name() != task->get_name()) {
621bool AsyncTaskManager::
623 TaskChains::const_iterator tci;
624 for (tci = _task_chains.begin();
625 tci != _task_chains.end();
627 AsyncTaskChain *chain = (*tci);
628 if (chain->do_has_task(task)) {
639void AsyncTaskManager::
640do_output(std::ostream &out)
const {
641 out << get_type() <<
" " << get_name()
642 <<
"; " << _num_tasks <<
" tasks";
648void AsyncTaskManager::
650 nassertv(_global_ptr ==
nullptr);
653 _global_ptr =
new AsyncTaskManager(
"TaskManager");
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The AsyncTaskChain is a subset of the AsyncTaskManager.
A list of tasks, for instance as returned by some of the AsyncTaskManager query functions.
get_num_tasks
Returns the number of AsyncTasks in the collection.
void add_task(AsyncTask *task)
Adds a new AsyncTask to the collection.
get_task
Returns the nth AsyncTask in the collection.
void add_tasks_from(const AsyncTaskCollection &other)
Adds all the AsyncTasks indicated in the other collection to this task.
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
get_num_task_chains
Returns the number of different task chains.
void wait_for_tasks()
Blocks until the task list is empty.
bool remove(AsyncTask *task)
Removes the indicated task from the active queue.
void add(AsyncTask *task)
Adds the indicated task to the active queue.
AsyncTaskCollection find_tasks_matching(const GlobPattern &pattern) const
Returns the list of tasks found whose name matches the indicated glob pattern, e.g.
void stop_threads()
Stops any threads that are currently running.
void poll()
Runs through all the tasks in the task list, once, if the task manager is running in single-threaded ...
AsyncTaskChain * find_task_chain(const std::string &name)
Searches a new AsyncTaskChain of the indicated name and returns it if it exists, or NULL otherwise.
void cleanup()
Stops all threads and messily empties the task list.
get_sleeping_tasks
Returns the set of tasks that are sleeping (and not active) on the task manager, at the time of the c...
get_next_wake_time
Returns the scheduled time (on the manager's clock) of the next sleeping task, on any task chain,...
AsyncTaskChain * make_task_chain(const std::string &name)
Creates a new AsyncTaskChain of the indicated name and stores it within the AsyncTaskManager.
get_tasks
Returns the set of tasks that are active or sleeping on the task manager, at the time of the call.
AsyncTask * find_task(const std::string &name) const
Returns the first task found with the indicated name, or NULL if there is no task with the indicated ...
get_active_tasks
Returns the set of tasks that are active (and not sleeping) on the task manager, at the time of the c...
get_task_chain
Returns the nth task chain.
bool has_task(AsyncTask *task) const
Returns true if the indicated task has been added to this AsyncTaskManager, false otherwise.
bool remove_task_chain(const std::string &name)
Removes the AsyncTaskChain of the indicated name.
void start_threads()
Starts any requested threads to service the tasks on the queue.
AsyncTaskCollection find_tasks(const std::string &name) const
Returns the list of tasks found with the indicated name.
This class represents a concrete task performed by an AsyncManager.
bool remove()
Removes the task from its active manager, if any, and makes the state S_inactive (or possible S_servi...
A ClockObject keeps track of elapsed real time and discrete time.
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
std::string get_const_prefix() const
Returns the initial part of the pattern before the first glob character.
bool matches(const std::string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
A base class for all things which can have a name.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.