00001 // -*- C++ -*- */ 00002 // 00003 // High_Res_Timer.inl,v 4.3 2005/10/28 16:14:52 ossama Exp 00004 00005 #include "ace/Global_Macros.h" 00006 00007 #if defined (ACE_WIN32) 00008 # include "ace/OS_NS_sys_time.h" 00009 #endif /* ACE_WIN32 */ 00010 00011 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00012 00013 // Be very careful before changing the calculations inside 00014 // ACE_High_Res_Timer. The precision matters and we are using integer 00015 // calculations not floating point. Also look closely at the emulated 64 00016 // bit int class (inside Basic_Types{h,i,cpp} before changing 00017 // anything. It's operator/ only returns 32 bits not 64 bits, among 00018 // other things. 00019 00020 ACE_INLINE void 00021 ACE_High_Res_Timer::hrtime_to_tv (ACE_Time_Value &tv, 00022 const ACE_hrtime_t hrt) 00023 { 00024 // The following are based on the units of global_scale_factor_ 00025 // being 1/microsecond. Therefore, dividing by it converts 00026 // clock ticks to microseconds. 00027 tv.sec ((long) (hrt / (ACE_UINT32) ACE_HR_SCALE_CONVERSION / 00028 global_scale_factor ())); 00029 00030 // Calculate usec in a manner that's compatible with ACE_U_LongLong. 00031 // hrt = (tv.sec * ACE_ONE_SECOND_IN_USECS + tv.usec) * global_scale_factor_ 00032 // tv.usec = hrt / global_scale_factor_ - tv.sec * ACE_ONE_SECOND_IN_USECS 00033 // That first term will be lossy, so factor out global_scale_factor_: 00034 // tv.usec = (hrt - tv.sec * ACE_ONE_SECOND_IN_USECS * global_scale_factor_)/ 00035 // global_scale_factor 00036 ACE_hrtime_t tmp = tv.sec (); 00037 tmp *= ((ACE_UINT32) ACE_HR_SCALE_CONVERSION * global_scale_factor ()); 00038 #if defined (ACE_WIN32) 00039 // Win32's scale factor is in ticks/msec, so multiply up to usec. 00040 ACE_hrtime_t subsec = hrt - tmp; // Remainder of ticks < 1sec 00041 ACE_UINT32 msec = (ACE_UINT32) (subsec / global_scale_factor ()); // #msec 00042 ACE_hrtime_t usec64 = subsec - (msec * global_scale_factor ()); 00043 # if defined (ACE_LACKS_LONGLONG_T) 00044 ACE_UINT32 usec = usec64.lo(); 00045 # else 00046 ACE_UINT32 usec = (ACE_UINT32) usec64; 00047 # endif // ACE_LACKS_LONGLONG_T 00048 // (tick * usec/msec) / tick/msec = usec 00049 usec = (usec * 1000) / (ACE_UINT32) global_scale_factor (); 00050 tv.usec ((msec * 1000) + usec); 00051 #else 00052 tv.usec ((long) ((hrt - tmp) / global_scale_factor ())); 00053 #endif 00054 } 00055 00056 00057 ACE_INLINE ACE_Time_Value 00058 ACE_High_Res_Timer::gettimeofday (const ACE_OS::ACE_HRTimer_Op op) 00059 { 00060 #if defined (ACE_WIN32) 00061 // Get the global scale factor if there isn't one yet. 00062 if (ACE_High_Res_Timer::global_scale_factor_status_ == 0) 00063 ACE_High_Res_Timer::global_scale_factor (); 00064 00065 // If there isn't a high-res timer, use gettimeofday (); 00066 if (ACE_High_Res_Timer::global_scale_factor_status_ == -1) 00067 return ACE_OS::gettimeofday (); 00068 #endif /* ACE_WIN32 */ 00069 00070 ACE_Time_Value tv; 00071 ACE_High_Res_Timer::hrtime_to_tv (tv, 00072 ACE_OS::gethrtime (op)); 00073 return tv; 00074 } 00075 00076 00077 // Get the current high res timer as the time of day. This is intended 00078 // to be used for a gettimeofday replacement in ACE_Timer_Queue and 00079 // derived classes so the timers will bebased on high res timers rather 00080 // than wall clock time. It uses the ACE_High_Res_Timer::gettimeofday 00081 // function, which is deprecated. If it gets removed, please move the 00082 // code down here, intact. 00083 ACE_INLINE ACE_Time_Value 00084 ACE_High_Res_Timer::gettimeofday_hr (void) 00085 { 00086 return ACE_High_Res_Timer::gettimeofday (); 00087 } 00088 00089 00090 ACE_INLINE ACE_hrtime_t 00091 ACE_High_Res_Timer::gettime (const ACE_OS::ACE_HRTimer_Op op) 00092 { 00093 #if defined (ACE_WIN32) 00094 // Get the global scale factor if there isn't one yet. 00095 if (ACE_High_Res_Timer::global_scale_factor_status_ == 0) 00096 ACE_High_Res_Timer::global_scale_factor (); 00097 00098 // If there isn't a high-res timer, use gettimeofday (); 00099 if (ACE_High_Res_Timer::global_scale_factor_status_ == -1) 00100 { 00101 ACE_Time_Value tv = ACE_OS::gettimeofday (); 00102 // Return the time in microseconds because the global_scale_factor_ 00103 // is 1. 00104 return tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec (); 00105 } 00106 #endif /* ACE_WIN32 */ 00107 00108 return ACE_OS::gethrtime (op); 00109 } 00110 00111 ACE_INLINE ACE_hrtime_t 00112 ACE_High_Res_Timer::elapsed_hrtime (const ACE_hrtime_t end, 00113 const ACE_hrtime_t start) 00114 { 00115 if (end > start) 00116 return end - start; 00117 return (~start + 1 + end); // Wrapped-around counter diff 00118 } 00119 00120 ACE_INLINE 00121 ACE_High_Res_Timer::~ACE_High_Res_Timer (void) 00122 { 00123 } 00124 00125 ACE_INLINE void 00126 ACE_High_Res_Timer::start (const ACE_OS::ACE_HRTimer_Op op) 00127 { 00128 ACE_TRACE ("ACE_High_Res_Timer::start"); 00129 this->start_ = ACE_High_Res_Timer::gettime (op); 00130 } 00131 00132 ACE_INLINE void 00133 ACE_High_Res_Timer::stop (const ACE_OS::ACE_HRTimer_Op op) 00134 { 00135 ACE_TRACE ("ACE_High_Res_Timer::stop"); 00136 this->end_ = ACE_High_Res_Timer::gettime (op); 00137 } 00138 00139 ACE_INLINE void 00140 ACE_High_Res_Timer::start_incr (const ACE_OS::ACE_HRTimer_Op op) 00141 { 00142 ACE_TRACE ("ACE_High_Res_Timer::start_incr"); 00143 this->start_incr_ = ACE_High_Res_Timer::gettime (op); 00144 } 00145 00146 ACE_INLINE void 00147 ACE_High_Res_Timer::stop_incr (const ACE_OS::ACE_HRTimer_Op op) 00148 { 00149 ACE_TRACE ("ACE_High_Res_Timer::stop_incr"); 00150 this->total_ += 00151 ACE_High_Res_Timer::elapsed_hrtime (ACE_High_Res_Timer::gettime (op), 00152 this->start_incr_); 00153 } 00154 00155 ACE_INLINE void 00156 ACE_High_Res_Timer::elapsed_microseconds (ACE_hrtime_t &usecs) const 00157 { 00158 ACE_hrtime_t elapsed = ACE_High_Res_Timer::elapsed_hrtime (this->end_, 00159 this->start_); 00160 #if defined (ACE_WIN32) 00161 // Win32 scale factor is in msec 00162 // This could give overflow when measuring a long time with a 00163 // big global_scale_factor() (> 48 days with a 4Ghz tick freq.) 00164 // To be looked after in the future. 00165 usecs = (ACE_hrtime_t) ((elapsed * 1000) / global_scale_factor ()); 00166 #else 00167 usecs = (ACE_hrtime_t) (elapsed / global_scale_factor ()); 00168 #endif 00169 } 00170 00171 ACE_INLINE void 00172 ACE_High_Res_Timer::global_scale_factor (ACE_UINT32 gsf) 00173 { 00174 global_scale_factor_ = gsf; 00175 } 00176 00177 ACE_END_VERSIONED_NAMESPACE_DECL