Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/pstatserver/pStatThreadData.cxx

Go to the documentation of this file.
00001 // Filename: pStatThreadData.cxx
00002 // Created by:  drose (09Jul00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "pStatThreadData.h"
00020 
00021 #include <pStatFrameData.h>
00022 #include <pStatCollectorDef.h>
00023 #include <config_pstats.h>
00024 
00025 
00026 PStatFrameData PStatThreadData::_null_frame;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: PStatThreadData::Constructor
00030 //       Access: Public
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 PStatThreadData::
00034 PStatThreadData(const PStatClientData *client_data) :
00035   _client_data(client_data)
00036 {
00037   _first_frame_number = 0;
00038   _history = pstats_history;
00039 }
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: PStatThreadData::Destructor
00043 //       Access: Public
00044 //  Description:
00045 ////////////////////////////////////////////////////////////////////
00046 PStatThreadData::
00047 ~PStatThreadData() {
00048 }
00049 
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: PStatThreadData::is_empty
00053 //       Access: Public
00054 //  Description: Returns true if the structure contains no frames,
00055 //               false otherwise.
00056 ////////////////////////////////////////////////////////////////////
00057 bool PStatThreadData::
00058 is_empty() const {
00059   return _frames.empty();
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: PStatThreadData::get_latest_frame_number
00064 //       Access: Public
00065 //  Description: Returns the frame number of the most recent frame
00066 //               stored in the data.
00067 ////////////////////////////////////////////////////////////////////
00068 int PStatThreadData::
00069 get_latest_frame_number() const {
00070   nassertr(!_frames.empty(), 0);
00071   return _first_frame_number + _frames.size() - 1;
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: PStatThreadData::get_oldest_frame_number
00076 //       Access: Public
00077 //  Description: Returns the frame number of the oldest frame still
00078 //               stored in the data.
00079 ////////////////////////////////////////////////////////////////////
00080 int PStatThreadData::
00081 get_oldest_frame_number() const {
00082   nassertr(!_frames.empty(), 0);
00083   return _first_frame_number;
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: PStatThreadData::has_frame
00088 //       Access: Public
00089 //  Description: Returns true if we have received data for the
00090 //               indicated frame number from the client and we still
00091 //               have it stored, or false otherwise.
00092 ////////////////////////////////////////////////////////////////////
00093 bool PStatThreadData::
00094 has_frame(int frame_number) const {
00095   int rel_frame = frame_number - _first_frame_number;
00096 
00097   return (rel_frame >= 0 && rel_frame < (int)_frames.size() &&
00098           _frames[rel_frame] != (PStatFrameData *)NULL);
00099 }
00100 
00101 ////////////////////////////////////////////////////////////////////
00102 //     Function: PStatThreadData::get_frame
00103 //       Access: Public
00104 //  Description: Returns a FrameData structure associated with the
00105 //               indicated frame number.  If the frame data has not
00106 //               yet been received from the client, returns the newest
00107 //               frame older than the requested frame.
00108 ////////////////////////////////////////////////////////////////////
00109 const PStatFrameData &PStatThreadData::
00110 get_frame(int frame_number) const {
00111   int rel_frame = frame_number - _first_frame_number;
00112   int num_frames = _frames.size();
00113   if (rel_frame >= num_frames) {
00114     rel_frame = num_frames - 1;
00115   }
00116 
00117   while (rel_frame >= 0 && _frames[rel_frame] == (PStatFrameData *)NULL) {
00118     rel_frame--;
00119   }
00120   if (rel_frame < 0) {
00121     // No frame data that old.  Return the oldest frame we've got.
00122     rel_frame = 0;
00123     while (rel_frame < num_frames &&
00124            _frames[rel_frame] == (PStatFrameData *)NULL) {
00125       rel_frame++;
00126     }
00127   }
00128 
00129   if (rel_frame >= 0 && rel_frame < num_frames) {
00130     PStatFrameData *frame = _frames[rel_frame];
00131     nassertr(frame != (PStatFrameData *)NULL, _null_frame);
00132     nassertr(frame->get_start() >= 0.0, _null_frame);
00133     return *frame;
00134   }
00135 
00136   nassertr(_null_frame.get_start() >= 0.0, _null_frame);
00137   return _null_frame;
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: PStatThreadData::get_latest_time
00142 //       Access: Public
00143 //  Description: Returns the timestamp (in seconds elapsed since
00144 //               connection) of the latest available frame.
00145 ////////////////////////////////////////////////////////////////////
00146 float PStatThreadData::
00147 get_latest_time() const {
00148   nassertr(!_frames.empty(), 0.0);
00149   return _frames.back()->get_start();
00150 }
00151 
00152 ////////////////////////////////////////////////////////////////////
00153 //     Function: PStatThreadData::get_oldest_time
00154 //       Access: Public
00155 //  Description: Returns the timestamp (in seconds elapsed since
00156 //               connection) of the oldest available frame.
00157 ////////////////////////////////////////////////////////////////////
00158 float PStatThreadData::
00159 get_oldest_time() const {
00160   nassertr(!_frames.empty(), 0.0);
00161   return _frames.front()->get_start();
00162 }
00163 
00164 ////////////////////////////////////////////////////////////////////
00165 //     Function: PStatThreadData::get_frame_at_time
00166 //       Access: Public
00167 //  Description: Returns the FrameData structure associated with the
00168 //               latest frame not later than the indicated time.
00169 ////////////////////////////////////////////////////////////////////
00170 const PStatFrameData &PStatThreadData::
00171 get_frame_at_time(float time) const {
00172   return get_frame(get_frame_number_at_time(time));
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: PStatThreadData::get_frame_number_at_time
00177 //       Access: Public
00178 //  Description: Returns the frame number of the latest frame not
00179 //               later than the indicated time.
00180 //
00181 //               If the hint is nonnegative, it represents a frame
00182 //               number that we believe the correct answer to be near,
00183 //               which may speed the search for the frame.
00184 ////////////////////////////////////////////////////////////////////
00185 int PStatThreadData::
00186 get_frame_number_at_time(float time, int hint) const {
00187   hint -= _first_frame_number;
00188   if (hint >= 0 && hint < (int)_frames.size()) {
00189     if (_frames[hint] != (PStatFrameData *)NULL &&
00190         _frames[hint]->get_start() <= time) {
00191       // The hint might be right.  Scan forward from there.
00192       int i = hint + 1;
00193       while (i < (int)_frames.size() &&
00194              (_frames[i] == (PStatFrameData *)NULL ||
00195               _frames[i]->get_start() <= time)) {
00196         if (_frames[i] != (PStatFrameData *)NULL) {
00197           hint = i;
00198         }
00199         ++i;
00200       }
00201       return _first_frame_number + hint;
00202     }
00203   }
00204 
00205   // The hint is totally wrong.  Start from the end and work
00206   // backwards.
00207 
00208   int i = _frames.size() - 1;
00209   while (i >= 0) {
00210     const PStatFrameData *frame = _frames[i];
00211     if (frame != (PStatFrameData *)NULL && frame->get_start() <= time) {
00212       break;
00213     }
00214     --i;
00215   }
00216 
00217   return _first_frame_number + i;
00218 }
00219 
00220 ////////////////////////////////////////////////////////////////////
00221 //     Function: PStatThreadData::get_latest_frame
00222 //       Access: Public
00223 //  Description: Returns the FrameData associated with the most recent
00224 //               frame.
00225 ////////////////////////////////////////////////////////////////////
00226 const PStatFrameData &PStatThreadData::
00227 get_latest_frame() const {
00228   nassertr(!_frames.empty(), _null_frame);
00229   return *_frames.back();
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: PStatThreadData::get_frame_rate
00234 //       Access: Public
00235 //  Description: Computes the average frame rate over the past number
00236 //               of seconds, by counting up the number of frames
00237 //               elapsed in that time interval.
00238 ////////////////////////////////////////////////////////////////////
00239 float PStatThreadData::
00240 get_frame_rate(float time) const {
00241   if (_frames.empty()) {
00242     // No frames in the data at all; nothing to base the frame rate
00243     // on.
00244     return 0.0;
00245   }
00246 
00247   int now_i = _frames.size() - 1;
00248   while (now_i > 0 && _frames[now_i] == (PStatFrameData *)NULL) {
00249     now_i--;
00250   }
00251   if (now_i < 0) {
00252     // No frames have any real data.
00253     return 0.0;
00254   }
00255   nassertr(_frames[now_i] != (PStatFrameData *)NULL, 0.0);
00256 
00257   float now = _frames[now_i]->get_end();
00258   float then = now - time;
00259 
00260   int then_i = now_i;
00261   int last_good_i = now_i;
00262 
00263   while (then_i >= 0) {
00264     const PStatFrameData *frame = _frames[then_i];
00265     if (frame != (PStatFrameData *)NULL) {
00266       if (frame->get_start() > then) {
00267         last_good_i = then_i;
00268       } else {
00269         break;
00270       }
00271     }
00272     then_i--;
00273   }
00274 
00275   nassertr(last_good_i >= 0, 0.0);
00276   nassertr(_frames[last_good_i] != (PStatFrameData *)NULL, 0.0);
00277 
00278   int num_frames = now_i - last_good_i + 1;
00279   return (float)num_frames / (now - _frames[last_good_i]->get_start());
00280 }
00281 
00282 
00283 ////////////////////////////////////////////////////////////////////
00284 //     Function: PStatThreadData::set_history
00285 //       Access: Public
00286 //  Description: Sets the number of seconds worth of frames that will
00287 //               be retained by the ThreadData structure as each new
00288 //               frame is added.  This affects how old the oldest
00289 //               frame that may be queried is.
00290 ////////////////////////////////////////////////////////////////////
00291 void PStatThreadData::
00292 set_history(float time) {
00293   _history = time;
00294 }
00295 
00296 ////////////////////////////////////////////////////////////////////
00297 //     Function: PStatThreadData::get_history
00298 //       Access: Public
00299 //  Description: Returns the number of seconds worth of frames that
00300 //               will be retained by the ThreadData structure as each
00301 //               new frame is added.  This affects how old the oldest
00302 //               frame that may be queried is.
00303 ////////////////////////////////////////////////////////////////////
00304 float PStatThreadData::
00305 get_history() const {
00306   return _history;
00307 }
00308 
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: PStatThreadData::record_new_frame
00312 //       Access: Public
00313 //  Description: Makes room for and stores a new frame's worth of
00314 //               data.  Calling this function may cause old frame data
00315 //               to be discarded to make room, according to the amount
00316 //               of time set up via set_history().
00317 //
00318 //               The pointer will become owned by the PStatThreadData
00319 //               object and will be freed on destruction.
00320 ////////////////////////////////////////////////////////////////////
00321 void PStatThreadData::
00322 record_new_frame(int frame_number, PStatFrameData *frame_data) {
00323   nassertv(frame_data != (PStatFrameData *)NULL);
00324   nassertv(!frame_data->is_empty());
00325   float time = frame_data->get_start();
00326 
00327   // First, remove all the old frames that fall outside of our
00328   // history window.
00329   float oldest_allowable_time = time - _history;
00330   while (!_frames.empty() &&
00331          (_frames.front() == (PStatFrameData *)NULL ||
00332           _frames.front()->is_empty() ||
00333           _frames.front()->get_start() < oldest_allowable_time)) {
00334     if (_frames.front() != (PStatFrameData *)NULL) {
00335       delete _frames.front();
00336     }
00337     _frames.pop_front();
00338     _first_frame_number++;
00339   }
00340 
00341   // Now, add enough empty frame definitions to account for the latest
00342   // frame number.  This might involve some skips, since we don't
00343   // guarantee that we get all the frames in order or even at all.
00344   if (_frames.empty()) {
00345     _first_frame_number = frame_number;
00346     _frames.push_back(NULL);
00347 
00348   } else {
00349     while (_first_frame_number + (int)_frames.size() <= frame_number) {
00350       _frames.push_back(NULL);
00351     }
00352   }
00353 
00354   int index = frame_number - _first_frame_number;
00355   nassertv(index >= 0 && index < (int)_frames.size());
00356 
00357   if (_frames[index] != (PStatFrameData *)NULL) {
00358     nout << "Got repeated frame data for frame " << frame_number << "\n";
00359     delete _frames[index];
00360   }
00361 
00362   _frames[index] = frame_data;
00363 }
00364 

Generated on Fri May 2 03:21:40 2003 for Panda-Tool by doxygen1.3