mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
421 lines
15 KiB
C++
421 lines
15 KiB
C++
// Filename: pStatClientData.cxx
|
|
// Created by: drose (11Jul00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pStatClientData.h"
|
|
#include "pStatReader.h"
|
|
|
|
#include "pStatCollectorDef.h"
|
|
|
|
PStatCollectorDef PStatClientData::_null_collector(-1, "Unknown");
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PStatClientData::
|
|
PStatClientData(PStatReader *reader) :
|
|
_reader(reader)
|
|
{
|
|
_is_alive = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::Destructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PStatClientData::
|
|
~PStatClientData() {
|
|
Collectors::const_iterator ci;
|
|
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
|
delete (*ci)._def;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::is_alive
|
|
// Access: Public
|
|
// Description: Returns true if the data is actively getting filled
|
|
// by a connected client, or false if the client has
|
|
// terminated.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PStatClientData::
|
|
is_alive() const {
|
|
return _is_alive;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::close
|
|
// Access: Public
|
|
// Description: Closes the client connection if it is open.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PStatClientData::
|
|
close() {
|
|
if (_is_alive && _reader != (PStatReader *)NULL) {
|
|
_reader->close();
|
|
_reader = (PStatReader *)NULL;
|
|
_is_alive = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_num_collectors
|
|
// Access: Public
|
|
// Description: Returns the total number of collectors the Data
|
|
// knows about.
|
|
////////////////////////////////////////////////////////////////////
|
|
int PStatClientData::
|
|
get_num_collectors() const {
|
|
return _collectors.size();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::has_collector
|
|
// Access: Public
|
|
// Description: Returns true if the indicated collector has been
|
|
// defined by the client already, false otherwise. It
|
|
// is possible for the client to start streaming data
|
|
// before all of the collectors have been defined.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PStatClientData::
|
|
has_collector(int index) const {
|
|
return (index >= 0 && index < (int)_collectors.size() &&
|
|
_collectors[index]._def != (PStatCollectorDef *)NULL);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_collector_def
|
|
// Access: Public
|
|
// Description: Returns the nth collector definition.
|
|
////////////////////////////////////////////////////////////////////
|
|
const PStatCollectorDef &PStatClientData::
|
|
get_collector_def(int index) const {
|
|
if (!has_collector(index)) {
|
|
return _null_collector;
|
|
}
|
|
return *_collectors[index]._def;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_collector_name
|
|
// Access: Public
|
|
// Description: Returns the name of the indicated collector.
|
|
////////////////////////////////////////////////////////////////////
|
|
string PStatClientData::
|
|
get_collector_name(int index) const {
|
|
if (!has_collector(index)) {
|
|
return "Unknown";
|
|
}
|
|
const PStatCollectorDef *def = _collectors[index]._def;
|
|
return def->_name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_collector_fullname
|
|
// Access: Public
|
|
// Description: Returns the "full name" of the indicated collector.
|
|
// This will be the concatenation of all of the
|
|
// collector's parents' names (except Frame) and the
|
|
// collector's own name.
|
|
////////////////////////////////////////////////////////////////////
|
|
string PStatClientData::
|
|
get_collector_fullname(int index) const {
|
|
if (!has_collector(index)) {
|
|
return "Unknown";
|
|
}
|
|
|
|
const PStatCollectorDef *def = _collectors[index]._def;
|
|
if (def->_parent_index == 0) {
|
|
return def->_name;
|
|
} else {
|
|
return get_collector_fullname(def->_parent_index) + ":" + def->_name;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::set_collector_has_level
|
|
// Access: Public
|
|
// Description: Indicates whether the given collector has level data
|
|
// (and consequently, whether it should appear on the
|
|
// Levels menu).
|
|
//
|
|
// The return value is true if anything changed, false
|
|
// otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PStatClientData::
|
|
set_collector_has_level(int index, int thread_index, bool flag) {
|
|
bool any_changed = false;
|
|
slot_collector(index);
|
|
nassertr(index >= 0 && index < (int)_collectors.size(), false);
|
|
|
|
if (_collectors[index]._is_level.get_bit(thread_index) != flag) {
|
|
any_changed = true;
|
|
_collectors[index]._is_level.set_bit_to(thread_index, flag);
|
|
}
|
|
|
|
// Turning this on for a given collector also implicitly turns all
|
|
// of its ancestors.
|
|
if (flag) {
|
|
PStatCollectorDef *def = _collectors[index]._def;
|
|
if (def != (PStatCollectorDef *)NULL && def->_parent_index != 0) {
|
|
if (set_collector_has_level(def->_parent_index, thread_index, flag)) {
|
|
any_changed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return any_changed;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_collector_has_level
|
|
// Access: Public
|
|
// Description: Returns whether the given collector has level data
|
|
// (and consequently, whether it should appear on the
|
|
// Levels menu).
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PStatClientData::
|
|
get_collector_has_level(int index, int thread_index) const {
|
|
return (index >= 0 && index < (int)_collectors.size() &&
|
|
_collectors[index]._is_level.get_bit(thread_index));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_num_toplevel_collectors
|
|
// Access: Public
|
|
// Description: Returns the total number of collectors that are
|
|
// toplevel collectors. These are the collectors that
|
|
// are the children of "Frame", which is collector 0.
|
|
////////////////////////////////////////////////////////////////////
|
|
int PStatClientData::
|
|
get_num_toplevel_collectors() const {
|
|
return _toplevel_collectors.size();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_toplevel_collector
|
|
// Access: Public
|
|
// Description: Returns the collector index of the nth toplevel
|
|
// collector. Use this function to iterate through the
|
|
// n toplevel collectors indicated by
|
|
// get_num_toplevel_collectors().
|
|
////////////////////////////////////////////////////////////////////
|
|
int PStatClientData::
|
|
get_toplevel_collector(int n) const {
|
|
nassertr(n >= 0 && n < (int)_toplevel_collectors.size(), 0);
|
|
return _toplevel_collectors[n];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_num_threads
|
|
// Access: Public
|
|
// Description: Returns the total number of threads the Data
|
|
// knows about.
|
|
////////////////////////////////////////////////////////////////////
|
|
int PStatClientData::
|
|
get_num_threads() const {
|
|
return _threads.size();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::has_thread
|
|
// Access: Public
|
|
// Description: Returns true if the indicated thread has been
|
|
// defined by the client already, false otherwise. It
|
|
// is possible for the client to start streaming data
|
|
// before all of the threads have been defined.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PStatClientData::
|
|
has_thread(int index) const {
|
|
return (index >= 0 && index < (int)_threads.size() &&
|
|
!_threads[index]._name.empty());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_thread_name
|
|
// Access: Public
|
|
// Description: Returns the name of the indicated thread.
|
|
////////////////////////////////////////////////////////////////////
|
|
string PStatClientData::
|
|
get_thread_name(int index) const {
|
|
if (!has_thread(index)) {
|
|
return "Unknown";
|
|
}
|
|
return _threads[index]._name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_thread_data
|
|
// Access: Public
|
|
// Description: Returns the data associated with the indicated
|
|
// thread. This will create a thread definition if it
|
|
// does not already exist.
|
|
////////////////////////////////////////////////////////////////////
|
|
const PStatThreadData *PStatClientData::
|
|
get_thread_data(int index) const {
|
|
((PStatClientData *)this)->define_thread(index);
|
|
nassertr(index >= 0 && index < (int)_threads.size(), NULL);
|
|
return _threads[index]._data;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::get_child_distance
|
|
// Access: Public
|
|
// Description: Returns the number of Collectors between the
|
|
// indicated parent and the child Collector in the
|
|
// relationship graph. If child is the same as parent,
|
|
// returns zero. If child is an immediate child of
|
|
// parent, returns 1. If child is a grandchild of
|
|
// parent, returns 2, and so on. If child is not a
|
|
// descendant of parent at all, returns -1.
|
|
////////////////////////////////////////////////////////////////////
|
|
int PStatClientData::
|
|
get_child_distance(int parent, int child) const {
|
|
if (parent == child) {
|
|
return 0;
|
|
}
|
|
if (!has_collector(child) || child == 0) {
|
|
return -1;
|
|
}
|
|
int dist = get_child_distance(parent, get_collector_def(child)._parent_index);
|
|
if (dist == -1) {
|
|
return -1;
|
|
} else {
|
|
return dist + 1;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::add_collector
|
|
// Access: Public
|
|
// Description: Adds a new collector definition to the dataset.
|
|
// Presumably this is information just arrived from the
|
|
// client.
|
|
//
|
|
// The pointer will become owned by the PStatClientData
|
|
// object and will be freed on destruction.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PStatClientData::
|
|
add_collector(PStatCollectorDef *def) {
|
|
slot_collector(def->_index);
|
|
nassertv(def->_index >= 0 && def->_index < (int)_collectors.size());
|
|
|
|
if (_collectors[def->_index]._def != (PStatCollectorDef *)NULL) {
|
|
// Free the old definition, if any.
|
|
delete _collectors[def->_index]._def;
|
|
}
|
|
|
|
_collectors[def->_index]._def = def;
|
|
update_toplevel_collectors();
|
|
|
|
// If we already had the _is_level flag set, it should be
|
|
// immediately applied to all ancestors.
|
|
const BitArray &is_level = _collectors[def->_index]._is_level;
|
|
int max_threads = is_level.get_num_bits();
|
|
for (int thread_index = 0; thread_index < max_threads; ++thread_index) {
|
|
if (is_level.get_bit(thread_index)) {
|
|
set_collector_has_level(def->_parent_index, thread_index, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::define_thread
|
|
// Access: Public
|
|
// Description: Adds a new thread definition to the dataset.
|
|
// Presumably this is information just arrived from the
|
|
// client.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PStatClientData::
|
|
define_thread(int thread_index, const string &name) {
|
|
// A sanity check on the index number.
|
|
nassertv(thread_index < 1000);
|
|
|
|
// Make sure we have enough slots allocated.
|
|
while ((int)_threads.size() <= thread_index) {
|
|
_threads.push_back(Thread());
|
|
}
|
|
|
|
if (!name.empty()) {
|
|
_threads[thread_index]._name = name;
|
|
}
|
|
|
|
if (_threads[thread_index]._data.is_null()) {
|
|
_threads[thread_index]._data = new PStatThreadData(this);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::record_new_frame
|
|
// Access: Public
|
|
// Description: Makes room for and stores a new frame's worth of
|
|
// data associated with some particular thread (which
|
|
// may or may not have already been defined).
|
|
//
|
|
// The pointer will become owned by the PStatThreadData
|
|
// object and will be freed on destruction.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PStatClientData::
|
|
record_new_frame(int thread_index, int frame_number,
|
|
PStatFrameData *frame_data) {
|
|
define_thread(thread_index);
|
|
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
|
_threads[thread_index]._data->record_new_frame(frame_number, frame_data);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::slot_collector
|
|
// Access: Private
|
|
// Description: Makes sure there is an entry in the array for a
|
|
// collector with the given index number.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PStatClientData::
|
|
slot_collector(int collector_index) {
|
|
// A sanity check on the index number.
|
|
nassertv(collector_index < 10000);
|
|
|
|
while ((int)_collectors.size() <= collector_index) {
|
|
Collector collector;
|
|
collector._def = (PStatCollectorDef *)NULL;
|
|
_collectors.push_back(collector);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PStatClientData::update_toplevel_collectors
|
|
// Access: Private
|
|
// Description: Rebuilds the list of toplevel collectors.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PStatClientData::
|
|
update_toplevel_collectors() {
|
|
_toplevel_collectors.clear();
|
|
|
|
Collectors::const_iterator ci;
|
|
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
|
PStatCollectorDef *def = (*ci)._def;
|
|
if (def != (PStatCollectorDef *)NULL && def->_parent_index == 0) {
|
|
_toplevel_collectors.push_back(def->_index);
|
|
}
|
|
}
|
|
}
|