summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnny Willemsen <jwillemsen@users.noreply.github.com>2016-09-09 09:03:12 +0200
committerGitHub <noreply@github.com>2016-09-09 09:03:12 +0200
commit5a33d55ef56723226a3d4ac779ecd4fe96530c38 (patch)
tree15fadfbfb5a216a5310f21709e70e336e6f04ebb
parentd19738b3d2bd9488cd37e71301aed3008ab664db (diff)
parent58100d3aeae33252ad12446f620382734e8f02d2 (diff)
downloadATCD-5a33d55ef56723226a3d4ac779ecd4fe96530c38.tar.gz
Merge pull request #200 from INMarkus/Bug#4084-Patch
Fix for Bug 4084 - ACE_Time_Value::set(double) hangs on large numbers
-rw-r--r--ACE/ace/Time_Value.cpp66
-rw-r--r--ACE/ace/Time_Value.inl20
-rw-r--r--ACE/tests/Time_Value_Test.cpp45
3 files changed, 83 insertions, 48 deletions
diff --git a/ACE/ace/Time_Value.cpp b/ACE/ace/Time_Value.cpp
index 36ba22b8ae2..b390d815bc4 100644
--- a/ACE/ace/Time_Value.cpp
+++ b/ACE/ace/Time_Value.cpp
@@ -174,52 +174,30 @@ ACE_Time_Value::dump (void) const
void
ACE_Time_Value::normalize (bool saturate)
{
- // // ACE_OS_TRACE ("ACE_Time_Value::normalize");
- // From Hans Rohnert...
-
- if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS)
- {
- /*! \todo This loop needs some optimization.
- */
- if (!saturate) // keep the conditionnal expression outside the while loop to minimize performance cost
- do
- {
- ++this->tv_.tv_sec;
- this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
- }
- while (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS);
- else
- do
- if (this->tv_.tv_sec < ACE_Numeric_Limits<time_t>::max())
- {
- ++this->tv_.tv_sec;
- this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
- }
- else
- this->tv_.tv_usec = ACE_ONE_SECOND_IN_USECS - 1;
- while (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS);
- }
- else if (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS)
+ // ACE_OS_TRACE ("ACE_Time_Value::normalize");
+ if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS ||
+ this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS)
{
- /*! \todo This loop needs some optimization.
- */
- if (!saturate)
- do
- {
- --this->tv_.tv_sec;
- this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
- }
- while (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS);
+ time_t sec = abs(this->tv_.tv_usec) / ACE_ONE_SECOND_IN_USECS * (this->tv_.tv_usec > 0 ? 1 : -1);
+ suseconds_t usec = this->tv_.tv_usec - sec * ACE_ONE_SECOND_IN_USECS;
+
+ if (saturate && this->tv_.tv_sec > 0 && sec > 0 &&
+ ACE_Numeric_Limits<time_t>::max() - this->tv_.tv_sec < sec)
+ {
+ this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::max();
+ this->tv_.tv_usec = ACE_ONE_SECOND_IN_USECS - 1;
+ }
+ else if (saturate && this->tv_.tv_sec < 0 && sec < 0 &&
+ ACE_Numeric_Limits<time_t>::min() - this->tv_.tv_sec > sec)
+ {
+ this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::min();
+ this->tv_.tv_usec = -ACE_ONE_SECOND_IN_USECS + 1;
+ }
else
- do
- if (this->tv_.tv_sec > ACE_Numeric_Limits<time_t>::min())
- {
- --this->tv_.tv_sec;
- this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
- }
- else
- this->tv_.tv_usec = -ACE_ONE_SECOND_IN_USECS + 1;
- while (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS);
+ {
+ this->tv_.tv_sec += sec;
+ this->tv_.tv_usec = usec;
+ }
}
if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0)
diff --git a/ACE/ace/Time_Value.inl b/ACE/ace/Time_Value.inl
index a4b095033e7..98459b47713 100644
--- a/ACE/ace/Time_Value.inl
+++ b/ACE/ace/Time_Value.inl
@@ -70,10 +70,22 @@ ACE_INLINE void
ACE_Time_Value::set (double d)
{
// ACE_OS_TRACE ("ACE_Time_Value::set");
- time_t l = (time_t) d;
- this->tv_.tv_sec = l;
- this->tv_.tv_usec = (suseconds_t) ((d - (double) l) * ACE_ONE_SECOND_IN_USECS + .5);
- this->normalize ();
+ if (d < ACE_Numeric_Limits<time_t>::min())
+ {
+ this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::min();
+ this->tv_.tv_usec = -ACE_ONE_SECOND_IN_USECS + 1;
+ }
+ else if (d > ACE_Numeric_Limits<time_t>::max())
+ {
+ this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::max();
+ this->tv_.tv_usec = ACE_ONE_SECOND_IN_USECS - 1;
+ }
+ else
+ {
+ time_t l = (time_t) d;
+ this->tv_.tv_sec = l;
+ this->tv_.tv_usec = (suseconds_t) ((d - (double) l) * ACE_ONE_SECOND_IN_USECS + (d < 0 ? -0.5 : 0.5));
+ }
}
/// Initializes a timespec_t. Note that this approach loses precision
diff --git a/ACE/tests/Time_Value_Test.cpp b/ACE/tests/Time_Value_Test.cpp
index 5806d67179f..04ec4b3f553 100644
--- a/ACE/tests/Time_Value_Test.cpp
+++ b/ACE/tests/Time_Value_Test.cpp
@@ -115,6 +115,51 @@ run_main (int, ACE_TCHAR *[])
ACE_TEXT ("msec const test failed: %Q should be 42555\n"),
ms));
+ // Test setting double values
+ ACE_Time_Value d1(10, 500000);
+ ACE_Time_Value d2;
+ d2.set(10.5);
+
+ ACE_Time_Value d3(-10, -500000);
+ ACE_Time_Value d4;
+ d4.set(-10.5);
+
+ ACE_TEST_ASSERT (d1 == d2);
+ ACE_TEST_ASSERT (d3 == d4);
+ ACE_TEST_ASSERT (d1 + d3 == ACE_Time_Value::zero);
+ ACE_TEST_ASSERT (d3 + d1 == ACE_Time_Value::zero);
+ ACE_TEST_ASSERT (d2 + d4 == ACE_Time_Value::zero);
+ ACE_TEST_ASSERT (d4 + d2 == ACE_Time_Value::zero);
+ ACE_TEST_ASSERT (ACE_Time_Value::zero - d1 = d3);
+ ACE_TEST_ASSERT (ACE_Time_Value::zero - d3 = d1);
+ ACE_TEST_ASSERT (ACE_Time_Value::zero - d2 = d4);
+ ACE_TEST_ASSERT (ACE_Time_Value::zero - d4 = d2);
+
+ ACE_Time_Value d5;
+ d5.set(DBL_MAX);
+ ACE_TEST_ASSERT (d5 == ACE_Time_Value::max_time);
+
+ // Test performance of normalize()
+ ACE_Time_Value v1(ACE_Numeric_Limits<time_t>::max(),
+ ACE_Numeric_Limits<suseconds_t>::max());
+ ACE_Time_Value v2(ACE_Numeric_Limits<time_t>::min(),
+ ACE_Numeric_Limits<suseconds_t>::min());
+ ACE_Time_Value v3(ACE_Numeric_Limits<time_t>::max(),
+ ACE_Numeric_Limits<suseconds_t>::min());
+ ACE_Time_Value v4(ACE_Numeric_Limits<time_t>::min(),
+ ACE_Numeric_Limits<suseconds_t>::max());
+
+ v1.set(ACE_Numeric_Limits<time_t>::max(),
+ ACE_Numeric_Limits<suseconds_t>::max());
+ v2.set(ACE_Numeric_Limits<time_t>::min(),
+ ACE_Numeric_Limits<suseconds_t>::min());
+ v3.set(ACE_Numeric_Limits<time_t>::max(),
+ ACE_Numeric_Limits<suseconds_t>::min());
+ v4.set(ACE_Numeric_Limits<time_t>::min(),
+ ACE_Numeric_Limits<suseconds_t>::max());
+
+ v1.set(DBL_MAX);
+
// Test setting from ACE_UINT64
ms = 42555;
ACE_Time_Value msec_test3;