35 AsyncTaskManager(
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()) {
78 if (_num_tasks == 1) {
79 nassertv(_tasks_by_name.size() == 1);
80 TasksByName::const_iterator tbni = _tasks_by_name.begin();
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";
107 int AsyncTaskManager::
108 get_num_task_chains()
const {
110 return _task_chains.
size();
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);
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);
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));
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) {
257 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
258 if (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
273 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
275 while (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
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) {
297 if (pattern.
matches(task->get_name())) {
322 size_t num_removed = 0;
325 for (
size_t i = 0; i < num_tasks; ++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) {
365 chain->do_wait_for_tasks();
382 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
384 chain->do_stop_threads();
400 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
403 chain->do_start_threads();
416 TaskChains::const_iterator tci;
417 for (tci = _task_chains.
begin();
418 tci != _task_chains.
end();
433 get_active_tasks()
const {
437 TaskChains::const_iterator tci;
438 for (tci = _task_chains.
begin();
439 tci != _task_chains.
end();
453 get_sleeping_tasks()
const {
457 TaskChains::const_iterator tci;
458 for (tci = _task_chains.
begin();
459 tci != _task_chains.
end();
480 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
495 double AsyncTaskManager::
496 get_next_wake_time()
const {
499 bool got_any =
false;
500 double next_wake_time = -1.0;
502 TaskChains::const_iterator tci;
503 for (tci = _task_chains.
begin();
504 tci != _task_chains.
end();
507 double time = chain->do_get_next_wake_time();
511 next_wake_time = time;
513 next_wake_time = std::min(time, next_wake_time);
518 return next_wake_time;
524 void AsyncTaskManager::
525 output(std::ostream &out)
const {
533 void AsyncTaskManager::
534 write(std::ostream &out,
int indent_level)
const {
537 << get_type() <<
" " << get_name() <<
"\n";
539 TaskChains::const_iterator tci;
540 for (tci = _task_chains.
begin();
541 tci != _task_chains.
end();
544 if (chain->_num_tasks != 0) {
546 chain->do_write(out, indent_level + 2);
559 do_make_task_chain(
const string &name) {
562 TaskChains::const_iterator tci = _task_chains.insert(chain).first;
573 do_find_task_chain(
const string &name) {
576 TaskChains::const_iterator tci = _task_chains.find(chain);
577 if (tci != _task_chains.
end()) {
587 void AsyncTaskManager::
589 if (!task->get_name().empty()) {
591 TasksByName::iterator tbni = _tasks_by_name.lower_bound(task);
592 while (tbni != _tasks_by_name.end()) {
593 if ((*tbni) == task) {
594 _tasks_by_name.erase(tbni);
597 if ((*tbni)->get_name() != task->get_name()) {
615 bool AsyncTaskManager::
617 TaskChains::const_iterator tci;
618 for (tci = _task_chains.
begin();
619 tci != _task_chains.
end();
622 if (chain->do_has_task(task)) {
633 void AsyncTaskManager::
634 do_output(std::ostream &out)
const {
635 out << get_type() <<
" " << get_name()
636 <<
"; " << _num_tasks <<
" tasks";
642 void AsyncTaskManager::
644 nassertv(_global_ptr ==
nullptr);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void pop_back()
Removes the last element at the end of the vector.
bool remove(AsyncTask *task)
Removes the indicated task from the active queue.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool remove_task_chain(const std::string &name)
Removes the AsyncTaskChain of the indicated name.
bool remove()
Removes the task from its active manager, if any, and makes the state S_inactive (or possible S_servi...
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...
size_type_0 size() const
Returns the number of elements in the ordered vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void start_threads()
Starts any requested threads to service the tasks on the queue.
void cleanup()
Stops all threads and messily empties the task list.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void add_task(AsyncTask *task)
Adds a new AsyncTask to the collection.
A list of tasks, for instance as returned by some of the AsyncTaskManager query functions.
AsyncTaskCollection find_tasks_matching(const GlobPattern &pattern) const
Returns the list of tasks found whose name matches the indicated glob pattern, e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
get_task_chain
Returns the nth task chain.
void unlock()
Alias for release() to match C++11 semantics.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
bool matches(const std::string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
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.
bool has_task(AsyncTask *task) const
Returns true if the indicated task has been added to this AsyncTaskManager, false otherwise.
A base class for all things which can have a name.
void wait_for_tasks()
Blocks until the task list is empty.
void stop_threads()
Stops any threads that are currently running.
void add(AsyncTask *task)
Adds the indicated task to the active queue.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
AsyncTaskChain * make_task_chain(const std::string &name)
Creates a new AsyncTaskChain of the indicated name and stores it within the AsyncTaskManager.
A ClockObject keeps track of elapsed real time and discrete time.
void add_tasks_from(const AsyncTaskCollection &other)
Adds all the AsyncTasks indicated in the other collection to this task.
std::string get_const_prefix() const
Returns the initial part of the pattern before the first glob character.
AsyncTaskCollection find_tasks(const std::string &name) const
Returns the list of tasks found with the indicated name.
The AsyncTaskChain is a subset of the AsyncTaskManager.
void ref() const
Explicitly increments the reference count.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
This class represents a concrete task performed by an AsyncManager.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void lock()
Alias for acquire() to match C++11 semantics.
get_num_tasks
Returns the number of AsyncTasks in the collection.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 ...
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
void poll()
Runs through all the tasks in the task list, once, if the task manager is running in single-threaded ...