|
|
@@ -24,6 +24,7 @@
|
|
|
#include "pStatTimer.h"
|
|
|
#include "clockObject.h"
|
|
|
#include <algorithm>
|
|
|
+#include <stdio.h> // For sprintf/snprintf
|
|
|
|
|
|
TypeHandle AsyncTaskChain::_type_handle;
|
|
|
|
|
|
@@ -507,15 +508,7 @@ service_one_task(AsyncTaskChain::AsyncTaskChainThread *thread) {
|
|
|
task->_state = AsyncTask::S_servicing;
|
|
|
task->_servicing_thread = thread;
|
|
|
|
|
|
- // Now release the chain lock while we actually service the
|
|
|
- // task.
|
|
|
- _manager->_lock.release();
|
|
|
- AsyncTask::DoneStatus ds = task->do_task();
|
|
|
-
|
|
|
- // Now we have to re-acquire the chain lock, so we can put the
|
|
|
- // task back on the queue (and so we can return with the lock
|
|
|
- // still held).
|
|
|
- _manager->_lock.lock();
|
|
|
+ AsyncTask::DoneStatus ds = task->unlock_and_do_task();
|
|
|
|
|
|
if (thread != (AsyncTaskChain::AsyncTaskChainThread *)NULL) {
|
|
|
thread->_servicing = NULL;
|
|
|
@@ -801,8 +794,28 @@ do_poll() {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void AsyncTaskChain::
|
|
|
do_write(ostream &out, int indent_level) const {
|
|
|
- indent(out, indent_level)
|
|
|
- << get_type() << " " << get_name() << "\n";
|
|
|
+ if (has_name()) {
|
|
|
+ indent(out, indent_level)
|
|
|
+ << get_name() << "\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ static const size_t buffer_size = 1024;
|
|
|
+ char buffer[buffer_size];
|
|
|
+ sprintf(buffer, " %-32s %8s %8s %8s %8s %6s",
|
|
|
+ "Task",
|
|
|
+ "sleep(s)",
|
|
|
+ "dt(ms)", "avg", "max",
|
|
|
+ "sort");
|
|
|
+ nassertv(strlen(buffer) < buffer_size);
|
|
|
+
|
|
|
+ indent(out, indent_level)
|
|
|
+ << buffer << "\n";
|
|
|
+
|
|
|
+ indent(out, indent_level);
|
|
|
+ for (int i = 0; i < 32+8+8+8+8+6+7; ++i) {
|
|
|
+ out << '-';
|
|
|
+ }
|
|
|
+ out << "\n";
|
|
|
|
|
|
// Collect a list of all active tasks, then sort them into order for
|
|
|
// output.
|
|
|
@@ -818,55 +831,78 @@ do_write(ostream &out, int indent_level) const {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!tasks.empty()) {
|
|
|
- indent(out, indent_level + 2)
|
|
|
- << "Active tasks:\n";
|
|
|
+ sort(tasks.begin(), tasks.end(), AsyncTaskSortPriority());
|
|
|
|
|
|
- sort(tasks.begin(), tasks.end(), AsyncTaskSortPriority());
|
|
|
+ double now = _manager->_clock->get_frame_time();
|
|
|
|
|
|
- // Since AsyncTaskSortPriority() sorts backwards (because of STL's
|
|
|
- // push_heap semantics), we go through the task list in reverse
|
|
|
- // order to print them forwards.
|
|
|
- TaskHeap::reverse_iterator ti;
|
|
|
- int current_sort = tasks.back()->get_sort() - 1;
|
|
|
- for (ti = tasks.rbegin(); ti != tasks.rend(); ++ti) {
|
|
|
- AsyncTask *task = (*ti);
|
|
|
- if (task->get_sort() != current_sort) {
|
|
|
- current_sort = task->get_sort();
|
|
|
- indent(out, indent_level + 2)
|
|
|
- << "sort = " << current_sort << "\n";
|
|
|
- }
|
|
|
- if (task->_state == AsyncTask::S_servicing) {
|
|
|
- indent(out, indent_level + 3)
|
|
|
- << "*" << *task << "\n";
|
|
|
- } else {
|
|
|
- indent(out, indent_level + 4)
|
|
|
- << *task << "\n";
|
|
|
- }
|
|
|
- }
|
|
|
+ // Since AsyncTaskSortPriority() sorts backwards (because of STL's
|
|
|
+ // push_heap semantics), we go through the task list in reverse
|
|
|
+ // order to print them forwards.
|
|
|
+ TaskHeap::reverse_iterator ti;
|
|
|
+ int current_sort = tasks.back()->get_sort() - 1;
|
|
|
+ for (ti = tasks.rbegin(); ti != tasks.rend(); ++ti) {
|
|
|
+ AsyncTask *task = (*ti);
|
|
|
+ write_task_line(out, indent_level, task, now);
|
|
|
}
|
|
|
|
|
|
- if (!_sleeping.empty()) {
|
|
|
- indent(out, indent_level + 2)
|
|
|
- << "Sleeping tasks:\n";
|
|
|
- double now = _manager->_clock->get_frame_time();
|
|
|
-
|
|
|
- // Instead of iterating through the _sleeping list in heap order,
|
|
|
- // copy it and then use repeated pops to get it out in sorted
|
|
|
- // order, for the user's satisfaction.
|
|
|
- TaskHeap sleeping = _sleeping;
|
|
|
- while (!sleeping.empty()) {
|
|
|
- PT(AsyncTask) task = sleeping.front();
|
|
|
- pop_heap(sleeping.begin(), sleeping.end(), AsyncTaskSortWakeTime());
|
|
|
- sleeping.pop_back();
|
|
|
-
|
|
|
- indent(out, indent_level + 4)
|
|
|
- << task->get_wake_time() - now << "s: "
|
|
|
- << *task << "\n";
|
|
|
- }
|
|
|
+ // Instead of iterating through the _sleeping list in heap order,
|
|
|
+ // copy it and then use repeated pops to get it out in sorted
|
|
|
+ // order, for the user's satisfaction.
|
|
|
+ TaskHeap sleeping = _sleeping;
|
|
|
+ while (!sleeping.empty()) {
|
|
|
+ PT(AsyncTask) task = sleeping.front();
|
|
|
+ pop_heap(sleeping.begin(), sleeping.end(), AsyncTaskSortWakeTime());
|
|
|
+ sleeping.pop_back();
|
|
|
+
|
|
|
+ write_task_line(out, indent_level, task, now);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskChain::write_task_line
|
|
|
+// Access: Protected
|
|
|
+// Description: Writes a single line for a task in the report
|
|
|
+// generated by do_write(). Assumes the lock is already
|
|
|
+// held.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void AsyncTaskChain::
|
|
|
+write_task_line(ostream &out, int indent_level, AsyncTask *task, double now) const {
|
|
|
+ char servicing_flag = ' ';
|
|
|
+ if (task->_state == AsyncTask::S_servicing) {
|
|
|
+ servicing_flag = '*';
|
|
|
+ } else if (task->_state == AsyncTask::S_servicing_removed) {
|
|
|
+ servicing_flag = '-';
|
|
|
+ }
|
|
|
+
|
|
|
+ static const size_t buffer_size = 1024;
|
|
|
+ char buffer[buffer_size];
|
|
|
+
|
|
|
+ if (task->_state == AsyncTask::S_sleeping) {
|
|
|
+ // For sleeping tasks, include the wake time, as an elapsed time
|
|
|
+ // in seconds.
|
|
|
+ string name = task->get_name().substr(0, 32);
|
|
|
+ sprintf(buffer, "%c%-32s %8.1f %8.1f %8.1f %8.1f %6d",
|
|
|
+ servicing_flag, name.c_str(),
|
|
|
+ task->_wake_time - now,
|
|
|
+ task->_dt * 1000.0, task->get_average_dt() * 1000.0,
|
|
|
+ task->_max_dt * 1000.0,
|
|
|
+ task->_sort);
|
|
|
+ } else {
|
|
|
+ // For active tasks, don't include a wake time. This means we
|
|
|
+ // have more space for the name.
|
|
|
+ string name = task->get_name().substr(0, 41);
|
|
|
+ sprintf(buffer, "%c%-41s %8.1f %8.1f %8.1f %6d",
|
|
|
+ servicing_flag, name.c_str(),
|
|
|
+ task->_dt * 1000.0, task->get_average_dt() * 1000.0,
|
|
|
+ task->_max_dt * 1000.0,
|
|
|
+ task->_sort);
|
|
|
+ }
|
|
|
+ nassertv(strlen(buffer) < buffer_size);
|
|
|
+
|
|
|
+ indent(out, indent_level)
|
|
|
+ << buffer << "\n";
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: AsyncTaskChain::AsyncTaskChainThread::Constructor
|
|
|
// Access: Public
|