Panda3D
|
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 }