1 #include "ace/Time_Value.h"
3 #if defined (ACE_HAS_ALLOC_HOOKS)
4 # include "ace/Malloc_Base.h"
5 #endif /* ACE_HAS_ALLOC_HOOKS */
7 #if !defined (__ACE_INLINE__)
8 #include "ace/Time_Value.inl"
9 #endif /* __ACE_INLINE__ */
11 #include "ace/Numeric_Limits.h"
12 #include "ace/If_Then_Else.h"
13 #include "ace/OS_NS_math.h"
14 #include "ace/Time_Policy.h"
19 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
21 /// Static constant representing `zero-time'.
22 /// Note: this object requires static construction.
23 const ACE_Time_Value
ACE_Time_Value::zero
;
25 /// Constant for maximum time representable. Note that this time
26 /// is not intended for use with select () or other calls that may
27 /// have *their own* implementation-specific maximum time representations.
28 /// Its primary use is in time computations such as those used by the
29 /// dynamic subpriority strategies in the ACE_Dynamic_Message_Queue class.
30 /// Note: this object requires static construction.
31 const ACE_Time_Value
ACE_Time_Value::max_time (
32 ACE_Numeric_Limits
<time_t>::max (),
33 ACE_ONE_SECOND_IN_USECS
- 1);
35 ACE_ALLOC_HOOK_DEFINE (ACE_Time_Value
)
37 /// Increment microseconds (the only reason this is here is to allow
38 /// the use of ACE_Atomic_Op with ACE_Time_Value).
40 ACE_Time_Value::operator ++ (int)
42 // ACE_OS_TRACE ("ACE_Time_Value::operator ++ (int)");
43 ACE_Time_Value
tv (*this);
49 ACE_Time_Value::operator ++ ()
51 // ACE_OS_TRACE ("ACE_Time_Value::operator ++ ()");
52 this->usec (this->usec () + 1);
57 /// Decrement microseconds (the only reason this is here is / to allow
58 /// the use of ACE_Atomic_Op with ACE_Time_Value).
60 ACE_Time_Value::operator -- (int)
62 // ACE_OS_TRACE ("ACE_Time_Value::operator -- (int)");
63 ACE_Time_Value
tv (*this);
69 ACE_Time_Value::operator -- ()
71 // ACE_OS_TRACE ("ACE_Time_Value::operator -- ()");
72 this->usec (this->usec () - 1);
77 #if defined (ACE_WIN32)
78 /// Static constant to remove time skew between FILETIME and POSIX
79 /// time. POSIX and Win32 use different epochs (Jan. 1, 1970 v.s.
80 /// Jan. 1, 1601). The following constant defines the difference
83 /// In the beginning (Jan. 1, 1601), there was no time and no computer.
84 /// And Bill said: "Let there be time," and there was time....
85 const DWORDLONG
ACE_Time_Value::FILETIME_to_timval_skew
=
86 ACE_INT64_LITERAL (0x19db1ded53e8000);
88 /// Initializes the ACE_Time_Value object from a Win32 FILETIME
89 ACE_Time_Value::ACE_Time_Value (const FILETIME
&file_time
)
91 // // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value");
92 this->set (file_time
);
95 void ACE_Time_Value::set (const FILETIME
&file_time
)
97 // Initializes the ACE_Time_Value object from a Win32 FILETIME
98 // Don't use a struct initializer, gcc don't like it.
99 ULARGE_INTEGER _100ns
;
100 _100ns
.LowPart
= file_time
.dwLowDateTime
;
101 _100ns
.HighPart
= file_time
.dwHighDateTime
;
103 _100ns
.QuadPart
-= ACE_Time_Value::FILETIME_to_timval_skew
;
105 // Convert 100ns units to seconds;
106 this->tv_
.tv_sec
= (time_t) (_100ns
.QuadPart
/ (10000 * 1000));
107 // Convert remainder to microseconds;
108 this->tv_
.tv_usec
= (suseconds_t
) ((_100ns
.QuadPart
% (10000 * 1000)) / 10);
113 /// Returns the value of the object as a Win32 FILETIME.
114 ACE_Time_Value::operator FILETIME () const
117 // ACE_OS_TRACE ("ACE_Time_Value::operator FILETIME");
119 ULARGE_INTEGER _100ns
;
120 _100ns
.QuadPart
= (((DWORDLONG
) this->tv_
.tv_sec
* (10000 * 1000) +
121 this->tv_
.tv_usec
* 10) +
122 ACE_Time_Value::FILETIME_to_timval_skew
);
124 file_time
.dwLowDateTime
= _100ns
.LowPart
;
125 file_time
.dwHighDateTime
= _100ns
.HighPart
;
129 #endif /* ACE_WIN32 */
132 ACE_Time_Value::now () const
134 ACE_System_Time_Policy systp
;
139 ACE_Time_Value::to_relative_time () const
141 ACE_System_Time_Policy systp
;
142 return (*this) - systp ();
146 ACE_Time_Value::to_absolute_time () const
148 ACE_System_Time_Policy systp
;
149 return (*this) + systp ();
153 ACE_Time_Value::duplicate () const
155 ACE_Time_Value
* tmp
= 0;
156 ACE_NEW_RETURN (tmp
, ACE_Time_Value (*this), 0);
161 ACE_Time_Value::dump () const
166 ACE_Time_Value::normalize (bool saturate
)
168 // ACE_OS_TRACE ("ACE_Time_Value::normalize");
169 if (this->tv_
.tv_usec
>= ACE_ONE_SECOND_IN_USECS
||
170 this->tv_
.tv_usec
<= -ACE_ONE_SECOND_IN_USECS
)
172 time_t const sec
= std::abs(this->tv_
.tv_usec
) / ACE_ONE_SECOND_IN_USECS
* (this->tv_
.tv_usec
> 0 ? 1 : -1);
173 suseconds_t
const usec
= static_cast<suseconds_t
> (this->tv_
.tv_usec
- sec
* ACE_ONE_SECOND_IN_USECS
);
175 if (saturate
&& this->tv_
.tv_sec
> 0 && sec
> 0 &&
176 ACE_Numeric_Limits
<time_t>::max() - this->tv_
.tv_sec
< sec
)
178 this->tv_
.tv_sec
= ACE_Numeric_Limits
<time_t>::max();
179 this->tv_
.tv_usec
= ACE_ONE_SECOND_IN_USECS
- 1;
181 else if (saturate
&& this->tv_
.tv_sec
< 0 && sec
< 0 &&
182 ACE_Numeric_Limits
<time_t>::min() - this->tv_
.tv_sec
> sec
)
184 this->tv_
.tv_sec
= ACE_Numeric_Limits
<time_t>::min();
185 this->tv_
.tv_usec
= -ACE_ONE_SECOND_IN_USECS
+ 1;
189 this->tv_
.tv_sec
+= sec
;
190 this->tv_
.tv_usec
= usec
;
194 if (this->tv_
.tv_sec
>= 1 && this->tv_
.tv_usec
< 0)
197 this->tv_
.tv_usec
+= ACE_ONE_SECOND_IN_USECS
;
199 // tv_sec in qnxnto is unsigned
200 #if !defined ( __QNX__)
201 else if (this->tv_
.tv_sec
< 0 && this->tv_
.tv_usec
> 0)
204 this->tv_
.tv_usec
-= ACE_ONE_SECOND_IN_USECS
;
211 ACE_Time_Value::operator *= (double d
)
213 // To work around the lack of precision of a long double to contain
214 // a 64-bits time_t + 6 digits after the decimal point for the usec part,
215 // we perform the multiplication of the 2 timeval parts separately.
217 // This extra precision step is adding a cost when transfering the
218 // seconds resulting from the usec multiplication. This operation
219 // correspond to the normalization process performed in normalize()
220 // but we must absolutly do it here because the usec multiplication
221 // result value could exceed what can be stored in a suseconds_t
224 // Since this is a costly operation, we try to detect as soon as
225 // possible if we are having a saturation in order to abort the rest
226 // of the computation.
227 using float_type
= ACE::If_Then_Else
<(sizeof(double) > sizeof(time_t)), double, long double>::result_type
;
229 float_type sec_total
= static_cast<float_type
> (this->sec());
232 // shall we saturate the result?
233 static const float_type max_int
=
234 ACE_Numeric_Limits
<time_t>::max() + 0.999999;
235 static const float_type min_int
=
236 ACE_Numeric_Limits
<time_t>::min() - 0.999999;
238 if (sec_total
> max_int
)
240 this->set(ACE_Numeric_Limits
<time_t>::max(), ACE_ONE_SECOND_IN_USECS
-1);
242 else if (sec_total
< min_int
)
244 this->set(ACE_Numeric_Limits
<time_t>::min(), -ACE_ONE_SECOND_IN_USECS
+1);
248 time_t time_sec
= static_cast<time_t> (sec_total
);
250 float_type usec_total
= this->usec();
253 // adding usec resulting from tv_sec mult
254 usec_total
+= (sec_total
-time_sec
) * ACE_ONE_SECOND_IN_USECS
;
256 // extract seconds component of the usec mult
257 sec_total
= usec_total
/ ACE_ONE_SECOND_IN_USECS
;
258 // keep remaining usec
261 usec_total
= (sec_total
- ACE_OS::floor(sec_total
));
265 usec_total
= (sec_total
- ACE_OS::ceil(sec_total
));
268 sec_total
-= usec_total
;
269 usec_total
*= ACE_ONE_SECOND_IN_USECS
;
271 // add the seconds component of the usec mult with the tv_sec mult prod.
272 sec_total
+= time_sec
;
274 // recheck for saturation
275 if (sec_total
> max_int
)
277 this->set (ACE_Numeric_Limits
<time_t>::max(), ACE_ONE_SECOND_IN_USECS
- 1);
279 else if (sec_total
< min_int
)
281 this->set (ACE_Numeric_Limits
<time_t>::min(), -ACE_ONE_SECOND_IN_USECS
+ 1);
285 time_sec
= static_cast<time_t> (sec_total
);
286 suseconds_t time_usec
= static_cast<suseconds_t
> (usec_total
);
288 // round up the result to save the last usec
289 if (time_usec
> 0 && (usec_total
- time_usec
) >= 0.5)
293 else if (time_usec
< 0 && (usec_total
- time_usec
) <= -0.5)
298 this->set (time_sec
, time_usec
);
304 std::ostream
&operator<<(std::ostream
&o
, const ACE_Time_Value
&v
)
306 char const oldFiller
= o
.fill ();
308 const timeval
*tv
= v
;
313 o
<< '.' << std::setw (6) << std::labs (tv
->tv_usec
);
315 else if (tv
->tv_usec
< 0)
316 o
<< "-0." << std::setw (6) << - tv
->tv_usec
;
321 o
<< '.'<< std::setw (6) << tv
->tv_usec
;
328 ACE_END_VERSIONED_NAMESPACE_DECL