15 #include "asyncTaskManager.h" 18 #include "mutexHolder.h" 20 #include "pStatClient.h" 21 #include "pStatTimer.h" 22 #include "clockObject.h" 23 #include "config_event.h" 36 AsyncTaskManager(
const string &name) :
38 _lock(
"AsyncTaskManager::_lock"),
44 do_make_task_chain(
"default");
67 if (task_cat.is_debug()) {
68 do_output(task_cat.debug());
75 while (!_task_chains.
empty()) {
83 if (_num_tasks == 1) {
84 nassertv(_tasks_by_name.size() == 1);
85 TasksByName::const_iterator tbni = _tasks_by_name.begin();
87 nassertv(task->_state == AsyncTask::S_servicing ||
88 task->_state == AsyncTask::S_servicing_removed);
89 task->_state = AsyncTask::S_servicing_removed;
95 nassertd(_num_tasks == 0 && _tasks_by_name.empty()) {
97 <<
"_num_tasks = " << _num_tasks <<
" _tasks_by_name = " << _tasks_by_name.size() <<
"\n";
98 TasksByName::const_iterator tbni;
99 for (tbni = _tasks_by_name.begin();
100 tbni != _tasks_by_name.end();
103 <<
" " << *(*tbni) <<
"\n";
118 return _task_chains.
size();
129 nassertr(n >= 0 && n < (
int)_task_chains.
size(), NULL);
130 return _task_chains[n];
144 return do_make_task_chain(name);
156 return do_find_task_chain(name);
174 TaskChains::iterator tci = _task_chains.find(chain);
175 if (tci == _task_chains.
end()) {
182 while (chain->_num_tasks != 0) {
185 <<
"Waiting for tasks on chain " << name <<
" to finish.\n";
186 chain->do_wait_for_tasks();
191 _task_chains.erase(tci);
204 nassertv(task->is_runnable());
209 if (task_cat.is_debug()) {
211 <<
"Adding " << *task <<
"\n";
214 if (task->_state == AsyncTask::S_servicing_removed) {
215 if (task->_manager ==
this) {
218 task->_state = AsyncTask::S_servicing;
223 nassertv(task->_manager == NULL &&
224 task->_state == AsyncTask::S_inactive);
225 nassertv(!do_has_task(task));
228 task->upon_birth(
this);
230 nassertv(task->_manager == NULL &&
231 task->_state == AsyncTask::S_inactive);
232 nassertv(!do_has_task(task));
237 <<
"Creating implicit AsyncTaskChain " << task->_chain_name
238 <<
" for " << get_type() <<
" " << get_name() <<
"\n";
239 chain = do_make_task_chain(task->_chain_name);
255 if (task->_manager !=
this) {
256 nassertr(!do_has_task(task),
false);
260 if (task->_state == AsyncTask::S_servicing_removed) {
283 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
284 if (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
302 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
304 while (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
324 TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
326 while (tbni != _tasks_by_name.end() && (*tbni)->get_name().substr(0, prefix.size()) == prefix) {
328 if (pattern.
matches(task->get_name())) {
351 return remove(tasks) != 0;
367 for (i = 0; i < num_tasks; ++i) {
370 if (task->_manager !=
this) {
372 nassertr(!do_has_task(task), num_removed);
374 nassertr(task->_chain->_manager ==
this, num_removed);
375 if (task_cat.is_debug()) {
377 <<
"Removing " << *task <<
"\n";
379 if (task->_chain->do_remove(task)) {
381 task->upon_death(
this,
false);
385 if (task_cat.is_debug()) {
387 <<
" (unable to remove " << *task <<
")\n";
406 while (_num_tasks > 0) {
410 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
412 chain->do_wait_for_tasks();
432 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
434 chain->do_stop_threads();
452 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
455 chain->do_start_threads();
470 TaskChains::const_iterator tci;
471 for (tci = _task_chains.
begin();
472 tci != _task_chains.
end();
494 TaskChains::const_iterator tci;
495 for (tci = _task_chains.
begin();
496 tci != _task_chains.
end();
517 TaskChains::const_iterator tci;
518 for (tci = _task_chains.
begin();
519 tci != _task_chains.
end();
544 for (
unsigned int i = 0; i < _task_chains.
size(); ++i) {
565 bool got_any =
false;
566 double next_wake_time = -1.0;
568 TaskChains::const_iterator tci;
569 for (tci = _task_chains.
begin();
570 tci != _task_chains.
end();
573 double time = chain->do_get_next_wake_time();
577 next_wake_time = time;
579 next_wake_time = min(time, next_wake_time);
584 return next_wake_time;
592 void AsyncTaskManager::
593 output(ostream &out)
const {
603 void AsyncTaskManager::
604 write(ostream &out,
int indent_level)
const {
606 indent(out, indent_level)
607 << get_type() <<
" " << get_name() <<
"\n";
609 TaskChains::const_iterator tci;
610 for (tci = _task_chains.
begin();
611 tci != _task_chains.
end();
614 if (chain->_num_tasks != 0) {
616 chain->do_write(out, indent_level + 2);
632 do_make_task_chain(
const string &name) {
635 TaskChains::const_iterator tci = _task_chains.insert(chain).first;
648 do_find_task_chain(
const string &name) {
651 TaskChains::const_iterator tci = _task_chains.find(chain);
652 if (tci != _task_chains.
end()) {
665 void AsyncTaskManager::
667 if (!task->get_name().empty()) {
670 TasksByName::iterator tbni = _tasks_by_name.lower_bound(task);
671 while (tbni != _tasks_by_name.end()) {
672 if ((*tbni) == task) {
673 _tasks_by_name.erase(tbni);
676 if ((*tbni)->get_name() != task->get_name()) {
697 bool AsyncTaskManager::
699 TaskChains::const_iterator tci;
700 for (tci = _task_chains.
begin();
701 tci != _task_chains.
end();
704 if (chain->do_has_task(task)) {
717 void AsyncTaskManager::
718 do_output(ostream &out)
const {
719 out << get_type() <<
" " << get_name()
720 <<
"; " << _num_tasks <<
" tasks";
729 void AsyncTaskManager::
bool matches(const string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
AsyncTaskChain * make_task_chain(const string &name)
Creates a new AsyncTaskChain of the indicated name and stores it within the AsyncTaskManager.
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.
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.
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.
bool remove_task_chain(const string &name)
Removes the AsyncTaskChain of the indicated name.
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.
double get_next_wake_time() const
Returns the scheduled time (on the manager's clock) of the next sleeping task, on any task chain...
AsyncTaskCollection get_tasks() const
Returns the set of tasks that are active or sleeping on the task manager, at the time of the call...
AsyncTaskCollection get_sleeping_tasks() const
Returns the set of tasks that are sleeping (and not active) on the task manager, at the time of the c...
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.
AsyncTask * get_task(int index) const
Returns the nth AsyncTask in the collection.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
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.
AsyncTask * find_task(const string &name) const
Returns the first task found with the indicated name, or NULL if there is no task with the indicated ...
void acquire() const
Grabs the mutex if it is available.
void wait_for_tasks()
Blocks until the task list is empty.
void stop_threads()
Stops any threads that are currently running.
AsyncTaskChain * get_task_chain(int n) const
Returns the nth task chain.
void add(AsyncTask *task)
Adds the indicated task to the active queue.
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.
string get_const_prefix() const
Returns the initial part of the pattern before the first glob character.
The AsyncTaskChain is a subset of the AsyncTaskManager.
AsyncTaskCollection get_active_tasks() const
Returns the set of tasks that are active (and not sleeping) on the task manager, at the time of the c...
int get_num_task_chains() const
Returns the number of different task chains.
int get_num_tasks() const
Returns the number of AsyncTasks in the collection.
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.
AsyncTaskCollection find_tasks(const string &name) const
Returns the list of tasks found with the indicated name.
AsyncTaskChain * find_task_chain(const string &name)
Searches a new AsyncTaskChain of the indicated name and returns it if it exists, or NULL otherwise...
void release() const
Releases the mutex.
TypeHandle is the identifier used to differentiate C++ class types.
This class can be used to test for string matches against standard Unix-shell filename globbing conve...
void poll()
Runs through all the tasks in the task list, once, if the task manager is running in single-threaded ...