Time_Value.cpp

Go to the documentation of this file.
00001 #include "ace/Time_Value.h"
00002 
00003 ACE_RCSID (ace,
00004            Time_Value,
00005            "$Id: Time_Value.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00006 
00007 
00008 #if !defined (__ACE_INLINE__)
00009 #include "ace/Time_Value.inl"
00010 #endif /* __ACE_INLINE__ */
00011 
00012 #include "ace/Numeric_Limits.h"
00013 #include "ace/If_Then_Else.h"
00014 
00015 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00016 
00017 // Static constant representing `zero-time'.
00018 // Note: this object requires static construction.
00019 const ACE_Time_Value ACE_Time_Value::zero;
00020 
00021 // Constant for maximum time representable.  Note that this time
00022 // is not intended for use with select () or other calls that may
00023 // have *their own* implementation-specific maximum time representations.
00024 // Its primary use is in time computations such as those used by the
00025 // dynamic subpriority strategies in the ACE_Dynamic_Message_Queue class.
00026 // Note: this object requires static construction.
00027 const ACE_Time_Value ACE_Time_Value::max_time (
00028   ACE_Numeric_Limits<time_t>::max (),
00029   ACE_ONE_SECOND_IN_USECS - 1);
00030 
00031 ACE_ALLOC_HOOK_DEFINE (ACE_Time_Value)
00032 
00033 // Increment microseconds (the only reason this is here is to allow
00034 // the use of ACE_Atomic_Op with ACE_Time_Value).
00035 
00036 ACE_Time_Value
00037 ACE_Time_Value::operator ++ (int)
00038 {
00039   // ACE_OS_TRACE ("ACE_Time_Value::operator ++ (int)");
00040   ACE_Time_Value tv (*this);
00041   ++*this;
00042   return tv;
00043 }
00044 
00045 ACE_Time_Value &
00046 ACE_Time_Value::operator ++ (void)
00047 {
00048   // ACE_OS_TRACE ("ACE_Time_Value::operator ++ (void)");
00049   this->usec (this->usec () + 1);
00050   this->normalize ();
00051   return *this;
00052 }
00053 
00054 // Decrement microseconds (the only reason this is here is / to allow
00055 // the use of ACE_Atomic_Op with ACE_Time_Value).
00056 
00057 ACE_Time_Value
00058 ACE_Time_Value::operator -- (int)
00059 {
00060   // ACE_OS_TRACE ("ACE_Time_Value::operator -- (int)");
00061   ACE_Time_Value tv (*this);
00062   --*this;
00063   return tv;
00064 }
00065 
00066 ACE_Time_Value &
00067 ACE_Time_Value::operator -- (void)
00068 {
00069   // ACE_OS_TRACE ("ACE_Time_Value::operator -- (void)");
00070   this->usec (this->usec () - 1);
00071   this->normalize ();
00072   return *this;
00073 }
00074 
00075 #if defined (ACE_WIN32)
00076 // Static constant to remove time skew between FILETIME and POSIX
00077 // time.  POSIX and Win32 use different epochs (Jan. 1, 1970 v.s.
00078 // Jan. 1, 1601).  The following constant defines the difference
00079 // in 100ns ticks.
00080 //
00081 // In the beginning (Jan. 1, 1601), there was no time and no computer.
00082 // And Bill said: "Let there be time," and there was time....
00083 # if defined (ACE_LACKS_LONGLONG_T)
00084 const ACE_U_LongLong ACE_Time_Value::FILETIME_to_timval_skew =
00085 ACE_U_LongLong (0xd53e8000, 0x19db1de);
00086 # else
00087 const DWORDLONG ACE_Time_Value::FILETIME_to_timval_skew =
00088 ACE_INT64_LITERAL (0x19db1ded53e8000);
00089 # endif
00090 
00091 //  Initializes the ACE_Time_Value object from a Win32 FILETIME
00092 
00093 ACE_Time_Value::ACE_Time_Value (const FILETIME &file_time)
00094 {
00095   // // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
00096   this->set (file_time);
00097 }
00098 
00099 void ACE_Time_Value::set (const FILETIME &file_time)
00100 {
00101   //  Initializes the ACE_Time_Value object from a Win32 FILETIME
00102 #if defined (ACE_LACKS_LONGLONG_T)
00103   ACE_U_LongLong LL_100ns(file_time.dwLowDateTime, file_time.dwHighDateTime);
00104   LL_100ns -= ACE_Time_Value::FILETIME_to_timval_skew;
00105   // Convert 100ns units to seconds;
00106   this->tv_.tv_sec = (long) (LL_100ns / ((double) (10000 * 1000)));
00107   // Convert remainder to microseconds;
00108   this->tv_.tv_usec = (suseconds_t)((LL_100ns % ((ACE_UINT32)(10000 * 1000))) / 10);
00109 #else
00110   // Don't use a struct initializer, gcc don't like it.
00111   ULARGE_INTEGER _100ns;
00112   _100ns.LowPart = file_time.dwLowDateTime;
00113   _100ns.HighPart = file_time.dwHighDateTime;
00114 
00115   _100ns.QuadPart -= ACE_Time_Value::FILETIME_to_timval_skew;
00116 
00117   // Convert 100ns units to seconds;
00118   this->tv_.tv_sec = (long) (_100ns.QuadPart / (10000 * 1000));
00119   // Convert remainder to microseconds;
00120   this->tv_.tv_usec = (suseconds_t) ((_100ns.QuadPart % (10000 * 1000)) / 10);
00121 #endif // ACE_LACKS_LONGLONG_T
00122   this->normalize ();
00123 }
00124 
00125 // Returns the value of the object as a Win32 FILETIME.
00126 
00127 ACE_Time_Value::operator FILETIME () const
00128 {
00129   FILETIME file_time;
00130   // ACE_OS_TRACE ("ACE_Time_Value::operator FILETIME");
00131 
00132 #if defined (ACE_LACKS_LONGLONG_T)
00133   ACE_U_LongLong LL_sec(this->tv_.tv_sec);
00134   ACE_U_LongLong LL_usec(this->tv_.tv_usec);
00135   ACE_U_LongLong LL_100ns = LL_sec * (ACE_UINT32)(10000 * 1000) +
00136                             LL_usec * (ACE_UINT32)10 +
00137                             ACE_Time_Value::FILETIME_to_timval_skew;
00138   file_time.dwLowDateTime = LL_100ns.lo();
00139   file_time.dwHighDateTime = LL_100ns.hi();
00140 #else
00141   ULARGE_INTEGER _100ns;
00142   _100ns.QuadPart = (((DWORDLONG) this->tv_.tv_sec * (10000 * 1000) +
00143                      this->tv_.tv_usec * 10) +
00144                      ACE_Time_Value::FILETIME_to_timval_skew);
00145 
00146   file_time.dwLowDateTime = _100ns.LowPart;
00147   file_time.dwHighDateTime = _100ns.HighPart;
00148 #endif //ACE_LACKS_LONGLONG_T
00149 
00150   return file_time;
00151 }
00152 
00153 #endif /* ACE_WIN32 */
00154 
00155 void
00156 ACE_Time_Value::dump (void) const
00157 {
00158 #if defined (ACE_HAS_DUMP)
00159   // ACE_OS_TRACE ("ACE_Time_Value::dump");
00160 #if 0
00161   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00162   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntv_sec_ = %d"), this->tv_.tv_sec));
00163   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntv_usec_ = %d\n"), this->tv_.tv_usec));
00164   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00165 #endif /* 0 */
00166 #endif /* ACE_HAS_DUMP */
00167 }
00168 
00169 void
00170 ACE_Time_Value::normalize (void)
00171 {
00172   // // ACE_OS_TRACE ("ACE_Time_Value::normalize");
00173   // From Hans Rohnert...
00174 
00175   if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS)
00176     {
00177       /*! \todo This loop needs some optimization.
00178        */
00179       do
00180         {
00181           ++this->tv_.tv_sec;
00182           this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
00183         }
00184       while (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS);
00185     }
00186   else if (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS)
00187     {
00188       /*! \todo This loop needs some optimization.
00189        */
00190       do
00191         {
00192           --this->tv_.tv_sec;
00193           this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
00194         }
00195       while (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS);
00196     }
00197 
00198   if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0)
00199     {
00200       --this->tv_.tv_sec;
00201       this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
00202     }
00203 // tv_sec in qnxnto is unsigned
00204 #if !defined ( __QNXNTO__)
00205   else if (this->tv_.tv_sec < 0 && this->tv_.tv_usec > 0)
00206     {
00207       ++this->tv_.tv_sec;
00208       this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
00209     }
00210 #endif /* __QNXNTO__  */
00211 }
00212 
00213 
00214 ACE_Time_Value &
00215 ACE_Time_Value::operator *= (double d)
00216 {
00217   // The floating type to be used in the computations.  It should be
00218   // large enough to hold a time_t.  We actually want a floating type
00219   // with enough digits in its mantissa to hold a time_t without
00220   // losing precision.  For example, if FLT_RADIX is 2 and
00221   // LDBL_MANT_DIG is 64, a long double has a 64 bit wide mantissa,
00222   // which would be sufficient to hold a 64 bit time_t value without
00223   // losing precision.
00224   //
00225   // For now we'll simply go with long double if it is larger than
00226   // time_t.  We're hosed if long double isn't large enough.
00227   typedef ACE::If_Then_Else<(sizeof (double) > sizeof (time_t)),
00228                             double,
00229                             long double>::result_type float_type;
00230 
00231   float_type time_total =
00232     (this->sec ()
00233      + static_cast<float_type> (this->usec ()) / ACE_ONE_SECOND_IN_USECS) * d;
00234 
00235   // shall we saturate the result?
00236   static const float_type max_int =
00237     ACE_Numeric_Limits<time_t>::max () + 0.999999;
00238   static const float_type min_int =
00239     ACE_Numeric_Limits<time_t>::min () - 0.999999;
00240 
00241   if (time_total > max_int)
00242     time_total = max_int;
00243   if (time_total < min_int)
00244     time_total = min_int;
00245 
00246   const time_t time_sec = static_cast<time_t> (time_total);
00247 
00248   time_total -= time_sec;
00249   time_total *= ACE_ONE_SECOND_IN_USECS;
00250 
00251   suseconds_t time_usec = static_cast<suseconds_t> (time_total);
00252 
00253   // round up the result to save the last usec
00254   if (time_usec > 0 && (time_total - time_usec) >= 0.5)
00255     ++time_usec;
00256   else if (time_usec < 0 && (time_total - time_usec) <= -0.5)
00257     --time_usec;
00258 
00259   this->set (time_sec, time_usec);
00260 
00261   return *this;
00262 }
00263 
00264 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 12:05:41 2008 for ACE by doxygen 1.3.6