Panda3D

clockObject.cxx

00001 // Filename: clockObject.cxx
00002 // Created by:  drose (17Feb00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "clockObject.h"
00016 #include "config_util.h"
00017 #include "configVariableEnum.h"
00018 #include "string_utils.h"
00019 #include "thread.h"
00020 
00021 void (*ClockObject::_start_clock_wait)() = ClockObject::dummy_clock_wait;
00022 void (*ClockObject::_start_clock_busy_wait)() = ClockObject::dummy_clock_wait;
00023 void (*ClockObject::_stop_clock_wait)() = ClockObject::dummy_clock_wait;
00024 
00025 PT(ClockObject) ClockObject::_global_clock;
00026 TypeHandle ClockObject::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: ClockObject::Constructor
00030 //       Access: Published
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 ClockObject::
00034 ClockObject() {
00035   _true_clock = TrueClock::get_global_ptr();
00036 
00037   // Each clock except for the application global clock is created in
00038   // M_normal mode.  The application global clock is later reset to
00039   // respect clock_mode, which comes from the Config.prc file.
00040   _mode = M_normal;
00041 
00042   _start_short_time = _true_clock->get_short_time();
00043   _start_long_time = _true_clock->get_long_time();
00044   _actual_frame_time = 0.0;
00045 
00046   ConfigVariableDouble max_dt
00047     ("max-dt", -1.0,
00048      PRC_DESC("Sets a limit on the value returned by ClockObject::get_dt().  If "
00049               "this value is less than zero, no limit is imposed; "
00050               "otherwise, this is the maximum value that will ever "
00051               "be returned by get_dt(), regardless of how much time "
00052               "has actually elapsed between frames.  See ClockObject::set_dt()."));
00053   ConfigVariableDouble clock_frame_rate
00054     ("clock-frame-rate", 1.0,
00055      PRC_DESC("In non-real-time clock mode, sets the number of frames per "
00056               "second that we should appear to be running.  In forced "
00057               "mode or limited mode, sets our target frame rate.  In "
00058               "normal mode, this has no effect.  See ClockObject::set_frame_rate()."));
00059   ConfigVariableDouble clock_degrade_factor
00060     ("clock-degrade-factor", 1.0,
00061      PRC_DESC("In degrade clock mode, returns the ratio by which the "
00062               "performance is degraded.  A value of 2.0 causes the "
00063               "clock to be slowed down by a factor of two (reducing "
00064               "performance to 1/2 what would be otherwise).  See ClockObject::set_degrade_factor()."));
00065   ConfigVariableDouble average_frame_rate_interval
00066     ("average-frame-rate-interval", 1.0,
00067      PRC_DESC("See ClockObject::set_average_frame_rate_interval()."));
00068 
00069   _max_dt = max_dt;
00070   _user_frame_rate = clock_frame_rate;
00071   _degrade_factor = clock_degrade_factor;
00072   _average_frame_rate_interval = average_frame_rate_interval;
00073 
00074   _error_count = _true_clock->get_error_count();
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: ClockObject::set_mode
00079 //       Access: Published
00080 //  Description: Changes the mode of the clock.  Normally, the clock
00081 //               is in mode M_normal. In this mode, each call to
00082 //               tick() will set the value returned by
00083 //               get_frame_time() to the current real time; thus, the
00084 //               clock simply reports time advancing.
00085 //
00086 //               Other possible modes:
00087 //
00088 //               M_non_real_time - the clock ignores real time
00089 //               completely; at each call to tick(), it pretends that
00090 //               exactly dt seconds have elapsed since the last call
00091 //               to tick().  You may set the value of dt with
00092 //               set_dt() or set_frame_rate().
00093 //
00094 //               M_limited - the clock will run as fast as it can, as
00095 //               in M_normal, but will not run faster than the rate
00096 //               specified by set_frame_rate().  If the application
00097 //               would run faster than this rate, the clock will slow
00098 //               down the application.
00099 //
00100 //               M_integer - the clock will run as fast as it can, but
00101 //               the rate will be constrained to be an integer
00102 //               multiple or divisor of the rate specified by
00103 //               set_frame_rate().  The clock will slow down the
00104 //               application a bit to guarantee this.
00105 //
00106 //               M_integer_limited - a combination of M_limited and
00107 //               M_integer; the clock will not run faster than
00108 //               set_frame_rate(), and if it runs slower, it will run
00109 //               at a integer divisor of that rate.
00110 //
00111 //               M_forced - the clock forces the application to run at
00112 //               the rate specified by set_frame_rate().  If the
00113 //               application would run faster than this rate, the
00114 //               clock will slow down the application; if the
00115 //               application would run slower than this rate, the
00116 //               clock slows down time so that the application
00117 //               believes it is running at the given rate.
00118 //
00119 //               M_degrade - the clock runs at real time, but the
00120 //               application is slowed down by a set factor of its
00121 //               frame rate, specified by set_degrade_factor().
00122 //
00123 //               M_slave - the clock does not advance, but relies on
00124 //               the user to call set_frame_time() and/or
00125 //               set_frame_count() each frame.
00126 ////////////////////////////////////////////////////////////////////
00127 void ClockObject::
00128 set_mode(ClockObject::Mode mode) {
00129   Thread *current_thread = Thread::get_current_thread();
00130   nassertv(current_thread->get_pipeline_stage() == 0);
00131   CDWriter cdata(_cycler, current_thread);
00132 
00133   _mode = mode;
00134 
00135   // In case we have set the clock to one of the modes that uses
00136   // _reported_frame_time_epoch, recompute the epoch.
00137   switch (_mode) {
00138   case M_non_real_time:
00139   case M_forced:
00140     cdata->_reported_frame_time_epoch = cdata->_reported_frame_time -
00141       cdata->_frame_count / _user_frame_rate;
00142     cdata->_dt = 1.0 / _user_frame_rate;
00143 
00144   default:
00145     break;
00146   }
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: ClockObject::set_real_time
00151 //       Access: Published
00152 //  Description: Resets the clock to the indicated time.  This
00153 //               changes only the real time of the clock as reported
00154 //               by get_real_time(), but does not immediately change
00155 //               the time reported by get_frame_time()--that will
00156 //               change after the next call to tick().  Also see
00157 //               reset(), set_frame_time(), and set_frame_count().
00158 ////////////////////////////////////////////////////////////////////
00159 void ClockObject::
00160 set_real_time(double time) {
00161 #ifdef NOTIFY_DEBUG
00162   // This is only a debug message, since it happens during normal
00163   // development, particularly at startup, or whenever you break into
00164   // the task loop.
00165   if (util_cat.is_debug() && this == _global_clock) {
00166     util_cat.debug()
00167       << "Adjusting global clock's real time by " << time - get_real_time()
00168       << " seconds.\n";
00169   }
00170 #endif  // NOTIFY_DEBUG
00171   _start_short_time = _true_clock->get_short_time() - time;
00172   _start_long_time = _true_clock->get_long_time() - time;
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: ClockObject::set_frame_time
00177 //       Access: Published
00178 //  Description: Changes the time as reported for the current frame to
00179 //               the indicated time.  Normally, the way to adjust the
00180 //               frame time is via tick(); this function is provided
00181 //               only for occasional special adjustments.
00182 ////////////////////////////////////////////////////////////////////
00183 void ClockObject::
00184 set_frame_time(double time, Thread *current_thread) {
00185   nassertv(current_thread->get_pipeline_stage() == 0);
00186 #ifdef NOTIFY_DEBUG
00187   if (this == _global_clock && _mode != M_slave) {
00188     util_cat.warning()
00189       << "Adjusting global clock's frame time by " << time - get_frame_time()
00190       << " seconds.\n";
00191   }
00192 #endif  // NOTIFY_DEBUG
00193   CDWriter cdata(_cycler, current_thread);
00194   _actual_frame_time = time;
00195   cdata->_reported_frame_time = time;
00196 
00197   // Recompute the epoch in case we are in a mode that relies on this.
00198   cdata->_reported_frame_time_epoch = cdata->_reported_frame_time -
00199     cdata->_frame_count / _user_frame_rate;
00200 }
00201 
00202 ////////////////////////////////////////////////////////////////////
00203 //     Function: ClockObject::set_frame_count
00204 //       Access: Published
00205 //  Description: Resets the number of frames counted to the indicated
00206 //               number.  Also see reset(), set_real_time(), and
00207 //               set_frame_time().
00208 ////////////////////////////////////////////////////////////////////
00209 void ClockObject::
00210 set_frame_count(int frame_count, Thread *current_thread) {
00211   nassertv(current_thread->get_pipeline_stage() == 0);
00212 #ifdef NOTIFY_DEBUG
00213   if (this == _global_clock && _mode != M_slave) {
00214     util_cat.warning()
00215       << "Adjusting global clock's frame count by " 
00216       << frame_count - get_frame_count() << " frames.\n";
00217   }
00218 #endif  // NOTIFY_DEBUG
00219   CDWriter cdata(_cycler, current_thread);
00220   cdata->_frame_count = frame_count;
00221 
00222   // Recompute the epoch in case we are in a mode that relies on this.
00223   cdata->_reported_frame_time_epoch = cdata->_reported_frame_time -
00224     cdata->_frame_count / _user_frame_rate;
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: ClockObject::set_dt
00229 //       Access: Published
00230 //  Description: In non-real-time mode, sets the number of seconds
00231 //               that should appear to elapse between frames.  In
00232 //               forced mode or limited mode, sets our target dt.  In
00233 //               normal mode, this has no effect.  
00234 //
00235 //               Also see set_frame_rate(), which is a different way
00236 //               to specify the same quantity.
00237 ////////////////////////////////////////////////////////////////////
00238 void ClockObject::
00239 set_dt(double dt) {
00240   if (_mode == M_slave) {
00241     // In M_slave mode, we can set any dt we like.
00242     CDWriter cdata(_cycler, Thread::get_current_thread());
00243     cdata->_dt = dt;
00244     if (dt != 0.0) {
00245       set_frame_rate(1.0 / dt);
00246     }
00247 
00248   } else {
00249     // In any other mode, we can only set non-zero dt.
00250     nassertv(dt != 0.0);
00251     set_frame_rate(1.0 / dt);
00252   }
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: ClockObject::set_frame_rate
00257 //       Access: Published
00258 //  Description: In non-real-time mode, sets the number of frames per
00259 //               second that we should appear to be running.  In forced
00260 //               mode or limited mode, sets our target frame rate.  In
00261 //               normal mode, this has no effect.
00262 //
00263 //               Also see set_dt(), which is a different way to
00264 //               specify the same quantity.
00265 ////////////////////////////////////////////////////////////////////
00266 void ClockObject::
00267 set_frame_rate(double frame_rate) {
00268   nassertv(frame_rate != 0.0);
00269 
00270   Thread *current_thread = Thread::get_current_thread();
00271   nassertv(current_thread->get_pipeline_stage() == 0);
00272 
00273   CDWriter cdata(_cycler, current_thread);
00274   _user_frame_rate = frame_rate;
00275 
00276   switch (_mode) {
00277   case M_non_real_time:
00278   case M_forced:
00279     cdata->_reported_frame_time_epoch = cdata->_reported_frame_time -
00280       cdata->_frame_count / _user_frame_rate;
00281     cdata->_dt = 1.0 / _user_frame_rate;
00282 
00283   default:
00284     break;
00285   }
00286 }
00287 
00288 ////////////////////////////////////////////////////////////////////
00289 //     Function: ClockObject::get_average_frame_rate
00290 //       Access: Published
00291 //  Description: Returns the average frame rate in number of frames
00292 //               per second over the last
00293 //               get_average_frame_rate_interval() seconds.  This
00294 //               measures the virtual frame rate if the clock is in
00295 //               M_non_real_time mode.
00296 ////////////////////////////////////////////////////////////////////
00297 double ClockObject::
00298 get_average_frame_rate(Thread *current_thread) const {
00299   CDStageReader cdata(_cycler, 0, current_thread);
00300   if (_ticks.size() <= 1) {
00301     return 0.0;
00302   } else {
00303     return _ticks.size() / (cdata->_reported_frame_time - _ticks.front());
00304   }
00305 }
00306 
00307 ////////////////////////////////////////////////////////////////////
00308 //     Function: ClockObject::get_max_frame_duration
00309 //       Access: Published
00310 //  Description: Returns the maximum frame duration over the last
00311 //               get_average_frame_rate_interval() seconds.
00312 ////////////////////////////////////////////////////////////////////
00313 double ClockObject::
00314 get_max_frame_duration(Thread *current_thread) const {
00315   CDStageReader cdata(_cycler, 0, current_thread);
00316   double max_duration = 0.0;
00317   double cur_duration = 0.0;
00318   size_t i;
00319   for (i = 0; i < _ticks.size() - 1; i++) {
00320     cur_duration = _ticks[i + 1] - _ticks[i];
00321     if (cur_duration > max_duration) {
00322       max_duration = cur_duration;
00323     }
00324   }
00325   return max_duration;
00326 }
00327 
00328 ////////////////////////////////////////////////////////////////////
00329 //     Function: ClockObject::calc_frame_time_deviation
00330 //       Access: Published
00331 //  Description: Returns the standard deviation of the frame times of
00332 //               the frames rendered over the past
00333 //               get_average_frame_rate_interval() seconds.  This
00334 //               number gives an estimate of the chugginess of the
00335 //               frame rate; if it is large, there is a large
00336 //               variation in the frame rate; if is small, all of the
00337 //               frames are consistent in length.
00338 //
00339 //               A large value might also represent just a recent
00340 //               change in frame rate, for instance, because the
00341 //               camera has just rotated from looking at a simple
00342 //               scene to looking at a more complex scene.
00343 ////////////////////////////////////////////////////////////////////
00344 double ClockObject::
00345 calc_frame_rate_deviation(Thread *current_thread) const {
00346   CDStageReader cdata(_cycler, 0, current_thread);
00347   if (_ticks.size() <= 1) {
00348     return 0.0;
00349   } else {
00350     double mean = (_ticks.back() - _ticks.front()) / (_ticks.size() - 1);
00351     size_t i;
00352     double sum_squares = 0.0;
00353     for (i = 0; i < _ticks.size() - 1; ++i) {
00354       double delta = _ticks[i + 1] - _ticks[i];
00355       double diff = (delta - mean);
00356       sum_squares += (diff * diff);
00357     }
00358     double deviation_2 = sum_squares / (_ticks.size() - 1);
00359     return sqrt(deviation_2);
00360   }
00361 }
00362 
00363 ////////////////////////////////////////////////////////////////////
00364 //     Function: ClockObject::tick
00365 //       Access: Published
00366 //  Description: Instructs the clock that a new frame has just begun.
00367 //               In normal, real-time mode, get_frame_time() will
00368 //               henceforth report the time as of this instant as the
00369 //               current start-of-frame time.  In non-real-time mode,
00370 //               get_frame_time() will be incremented by the value of
00371 //               dt.
00372 ////////////////////////////////////////////////////////////////////
00373 void ClockObject::
00374 tick(Thread *current_thread) {
00375   nassertv(current_thread->get_pipeline_stage() == 0);
00376   CDWriter cdata(_cycler, current_thread);
00377   double old_reported_time = cdata->_reported_frame_time;
00378 
00379   if (_mode != M_slave) {
00380     double old_time = _actual_frame_time;
00381     _actual_frame_time = get_real_time();
00382 
00383     // In case someone munged the clock last frame and sent us
00384     // backward in time, clamp the previous time to the current time
00385     // to make sure we don't report anything strange (or wait
00386     // interminably).
00387     old_time = min(old_time, _actual_frame_time);
00388 
00389     ++cdata->_frame_count;
00390     
00391     switch (_mode) {
00392     case M_normal:
00393       // Time runs as it will; we simply report time elapsing.
00394       cdata->_dt = _actual_frame_time - old_time;
00395       cdata->_reported_frame_time = _actual_frame_time;
00396       break;
00397       
00398     case M_non_real_time:
00399       // Ignore real time.  We always report the same interval having
00400       // elapsed each frame.
00401       cdata->_reported_frame_time = cdata->_reported_frame_time_epoch +
00402         cdata->_frame_count / _user_frame_rate;
00403       break;
00404       
00405     case M_limited:
00406       // If we are running faster than the desired interval, slow down.
00407       {
00408         double wait_until_time = old_time + 1.0 / _user_frame_rate;
00409         wait_until(wait_until_time);
00410         cdata->_dt = _actual_frame_time - old_time;
00411         cdata->_reported_frame_time = max(_actual_frame_time, wait_until_time);
00412       }
00413       break;
00414 
00415     case M_integer:
00416       {
00417         double dt = _actual_frame_time - old_time;
00418         double target_dt = 1.0 / _user_frame_rate;
00419         if (dt < target_dt) {
00420           // We're running faster than the desired interval, so slow
00421           // down to the next integer multiple of the frame rate.
00422           target_dt = target_dt / floor(target_dt / dt);
00423         } else {
00424           // We're running slower than the desired interval, so slow
00425           // down to the next integer divisor of the frame rate.
00426           target_dt = target_dt * ceil(dt / target_dt);
00427         }
00428         double wait_until_time = old_time + target_dt;
00429         wait_until(wait_until_time);
00430         cdata->_dt = target_dt;
00431         cdata->_reported_frame_time = wait_until_time;
00432       }
00433       break;
00434 
00435     case M_integer_limited:
00436       {
00437         double dt = _actual_frame_time - old_time;
00438         double target_dt = 1.0 / _user_frame_rate;
00439         if (dt < target_dt) {
00440           // We're running faster than the desired interval, so slow
00441           // down to the target frame rate.
00442 
00443         } else {
00444           // We're running slower than the desired interval, so slow
00445           // down to the next integer divisor of the frame rate.
00446           target_dt = target_dt * ceil(dt / target_dt);
00447         }
00448         double wait_until_time = old_time + target_dt;
00449         wait_until(wait_until_time);
00450         cdata->_dt = target_dt;
00451         cdata->_reported_frame_time = wait_until_time;
00452       }
00453       break;
00454       
00455     case M_forced:
00456       // If we are running faster than the desired interval, slow down.
00457       // If we are running slower than the desired interval, ignore that
00458       // and pretend we're running at the specified rate.
00459       wait_until(old_time + 1.0 / _user_frame_rate);
00460       cdata->_reported_frame_time = cdata->_reported_frame_time_epoch +
00461         cdata->_frame_count / _user_frame_rate;
00462       break;
00463       
00464     case M_degrade:
00465       // Each frame, wait a certain fraction of the previous frame's
00466       // time to degrade performance uniformly.
00467       cdata->_dt = (_actual_frame_time - old_time) * _degrade_factor;
00468       
00469       if (_degrade_factor < 1.0) {
00470         // If the degrade_factor is less than one, we want to simulate a
00471         // higher frame rate by incrementing the clock more slowly.
00472         cdata->_reported_frame_time += cdata->_dt;
00473         
00474       } else {
00475         // Otherwise, we simulate a lower frame rate by waiting until
00476         // the appropriate time has elapsed.
00477         wait_until(old_time + cdata->_dt);
00478         cdata->_reported_frame_time = _actual_frame_time;
00479       }
00480       
00481       break;
00482 
00483     case M_slave:
00484       // Handled above.
00485       break;
00486     }
00487   }
00488 
00489   if (_average_frame_rate_interval > 0.0) {
00490     _ticks.push_back(old_reported_time);
00491     while (_ticks.size() > 2 && 
00492            cdata->_reported_frame_time - _ticks.front() > _average_frame_rate_interval) {
00493       _ticks.pop_front();
00494     }
00495   }
00496 }
00497 
00498 ////////////////////////////////////////////////////////////////////
00499 //     Function: ClockObject::sync_frame_time
00500 //       Access: Published
00501 //  Description: Resets the frame time to the current real time.  This
00502 //               is similar to tick(), except that it does not advance
00503 //               the frame counter and does not affect dt.  This is
00504 //               intended to be used in the middle of a particularly
00505 //               long frame to compensate for the time that has
00506 //               already elapsed.
00507 //
00508 //               In non-real-time mode, this function has no effect
00509 //               (because in this mode all frames take the same length
00510 //               of time).
00511 ////////////////////////////////////////////////////////////////////
00512 void ClockObject::
00513 sync_frame_time(Thread *current_thread) {
00514   if (_mode == M_normal) {
00515     CDWriter cdata(_cycler, current_thread);
00516     cdata->_reported_frame_time = get_real_time();
00517   }
00518 }
00519 
00520 ////////////////////////////////////////////////////////////////////
00521 //     Function: ClockObject::wait_until
00522 //       Access: Private
00523 //  Description: Waits at the end of a frame until the indicated time
00524 //               has arrived.  This is used to implement M_forced and
00525 //               M_degrade.
00526 ////////////////////////////////////////////////////////////////////
00527 void ClockObject::
00528 wait_until(double want_time) {
00529   if (want_time <= _actual_frame_time) {
00530     return;
00531   }
00532 
00533 #ifdef DO_PSTATS
00534   (*_start_clock_wait)();
00535 #endif
00536 
00537   double wait_interval = (want_time - _actual_frame_time) - sleep_precision;
00538     
00539   if (wait_interval > 0.0) {
00540     Thread::sleep(wait_interval);
00541   }
00542 
00543 #ifdef DO_PSTATS
00544   (*_start_clock_busy_wait)();
00545 #endif
00546   
00547   // Now busy-wait until the actual time elapses.
00548   while (_actual_frame_time < want_time) {
00549     _actual_frame_time = get_real_time();
00550   }
00551 
00552 #ifdef DO_PSTATS
00553   (*_stop_clock_wait)();
00554 #endif
00555 }
00556 
00557 ////////////////////////////////////////////////////////////////////
00558 //     Function: ClockObject::make_global_clock
00559 //       Access: Private, Static
00560 //  Description: Called once per application to create the global
00561 //               clock object.
00562 ////////////////////////////////////////////////////////////////////
00563 void ClockObject::
00564 make_global_clock() {
00565   nassertv(_global_clock == (ClockObject *)NULL);
00566 
00567   ConfigVariableEnum<ClockObject::Mode> clock_mode
00568     ("clock-mode", ClockObject::M_normal,
00569      PRC_DESC("Specifies the mode of the global clock.  The default mode, normal, "
00570               "is a real-time clock; other modes allow non-real-time special "
00571               "effects like simulated reduced frame rate.  See "
00572               "ClockObject::set_mode()."));
00573 
00574   _global_clock = new ClockObject;
00575   _global_clock->set_mode(clock_mode);
00576 }
00577 
00578 ////////////////////////////////////////////////////////////////////
00579 //     Function: ClockObject::dummy_clock_wait
00580 //       Access: Private, Static
00581 //  Description: This no-op function is assigned as the initial
00582 //               pointer for _start_clock_wait and _stop_clock_wait,
00583 //               until the PStatClient comes along and replaces it.
00584 ////////////////////////////////////////////////////////////////////
00585 void ClockObject::
00586 dummy_clock_wait() {
00587 }
00588 
00589 ////////////////////////////////////////////////////////////////////
00590 //     Function: ClockObject::CData::Constructor
00591 //       Access: Public
00592 //  Description:
00593 ////////////////////////////////////////////////////////////////////
00594 ClockObject::CData::
00595 CData() {
00596   _frame_count = 0;
00597   _reported_frame_time = 0.0;
00598   _reported_frame_time_epoch = 0.0;
00599   _dt = 0.0;
00600 }
00601 
00602 ////////////////////////////////////////////////////////////////////
00603 //     Function: ClockObject::CData::make_copy
00604 //       Access: Public, Virtual
00605 //  Description:
00606 ////////////////////////////////////////////////////////////////////
00607 CycleData *ClockObject::CData::
00608 make_copy() const {
00609   return new CData(*this);
00610 }
00611 
00612 ////////////////////////////////////////////////////////////////////
00613 //     Function: ClockObject::Mode ostream operator
00614 //  Description:
00615 ////////////////////////////////////////////////////////////////////
00616 ostream &
00617 operator << (ostream &out, ClockObject::Mode mode) {
00618   switch (mode) {
00619   case ClockObject::M_normal:
00620     return out << "normal";
00621 
00622   case ClockObject::M_non_real_time:
00623     return out << "non-real-time";
00624 
00625   case ClockObject::M_limited:
00626     return out << "limited";
00627 
00628   case ClockObject::M_integer:
00629     return out << "integer";
00630 
00631   case ClockObject::M_integer_limited:
00632     return out << "integer_limited";
00633 
00634   case ClockObject::M_forced:
00635     return out << "forced";
00636 
00637   case ClockObject::M_degrade:
00638     return out << "degrade";
00639 
00640   case ClockObject::M_slave:
00641     return out << "slave";
00642   };
00643 
00644   return out << "**invalid ClockObject::Mode(" << (int)mode << ")**";
00645 }
00646 
00647 ////////////////////////////////////////////////////////////////////
00648 //     Function: ClockObject::Mode istream operator
00649 //  Description:
00650 ////////////////////////////////////////////////////////////////////
00651 istream &
00652 operator >> (istream &in, ClockObject::Mode &mode) {
00653   string word;
00654   in >> word;
00655 
00656   if (cmp_nocase_uh(word, "normal") == 0) {
00657     mode = ClockObject::M_normal;
00658   } else if (cmp_nocase_uh(word, "non-real-time") == 0) {
00659     mode = ClockObject::M_non_real_time;
00660   } else if (cmp_nocase_uh(word, "limited") == 0) {
00661     mode = ClockObject::M_limited;
00662   } else if (cmp_nocase_uh(word, "integer") == 0) {
00663     mode = ClockObject::M_integer;
00664   } else if (cmp_nocase_uh(word, "integer_limited") == 0) {
00665     mode = ClockObject::M_integer_limited;
00666   } else if (cmp_nocase_uh(word, "forced") == 0) {
00667     mode = ClockObject::M_forced;
00668   } else if (cmp_nocase_uh(word, "degrade") == 0) {
00669     mode = ClockObject::M_degrade;
00670   } else if (cmp_nocase_uh(word, "slave") == 0) {
00671     mode = ClockObject::M_slave;
00672   } else {
00673     util_cat->error()
00674       << "Invalid ClockObject::Mode: " << word << "\n";
00675     mode = ClockObject::M_normal;
00676   }
00677 
00678   return in;
00679 }
 All Classes Functions Variables Enumerations