From b226740d6536cc53173c4c426649c2b839f8603c Mon Sep 17 00:00:00 2001 From: Fred Hornsey Date: Fri, 29 Aug 2025 20:45:05 -0500 Subject: [PATCH 1/3] Time_Value & Floating-point std::chrono::duration `ACE_Time_Value` currently doesn't accept a `std::chrono::duration` with `Rep` that's a floating point type because it's using the modulus operator to separate the microseconds (`duration % seconds(1)`) and trying to use modulus with floating points causes a compile error. This changes it to use subtraction from the whole number of seconds (`duration - sec`) and adds a test for it. Also: - Simplify the `-=` and `+=` ops of `ACE_Time_Value` - Rewrite some of the testing in `Chrono_Test.cpp`. --- ACE/NEWS | 2 + ACE/ace/Time_Value.h | 24 ++--- ACE/tests/.gitignore | 19 ++-- ACE/tests/Chrono_Test.cpp | 187 +++++++++++--------------------------- 4 files changed, 77 insertions(+), 155 deletions(-) diff --git a/ACE/NEWS b/ACE/NEWS index cd9e09fe20e82..28715cdcc6b39 100644 --- a/ACE/NEWS +++ b/ACE/NEWS @@ -1,6 +1,8 @@ USER VISIBLE CHANGES BETWEEN ACE-8.0.5 and ACE-8.0.6 ==================================================== +. Support floating-point-based `std::chrono::duration` in `ACE_Time_Value` + USER VISIBLE CHANGES BETWEEN ACE-8.0.4 and ACE-8.0.5 ==================================================== diff --git a/ACE/ace/Time_Value.h b/ACE/ace/Time_Value.h index e716d0aa18776..53fbb71050d7a 100644 --- a/ACE/ace/Time_Value.h +++ b/ACE/ace/Time_Value.h @@ -118,13 +118,13 @@ class ACE_Export ACE_Time_Value template< class Rep, class Period > void set (const std::chrono::duration& duration) { - std::chrono::seconds const s { - std::chrono::duration_cast (duration)}; + using std::chrono::seconds; + using std::chrono::microseconds; + using std::chrono::duration_cast; - std::chrono::microseconds const usec { - std::chrono::duration_cast( - duration % std::chrono::seconds (1))}; - this->set (ACE_Utils::truncate_cast(s.count ()), ACE_Utils::truncate_cast(usec.count ())); + auto const sec = duration_cast (duration); + auto const usec = duration_cast (duration - sec); + this->set (ACE_Utils::truncate_cast (sec.count ()), ACE_Utils::truncate_cast (usec.count ())); } /// Converts from ACE_Time_Value format into milliseconds format. @@ -272,11 +272,7 @@ class ACE_Export ACE_Time_Value template< class Rep, class Period > ACE_Time_Value &operator += (const std::chrono::duration& duration) { - const ACE_Time_Value tv (duration); - this->sec (this->sec () + tv.sec ()); - this->usec (this->usec () + tv.usec ()); - this->normalize (); - return *this; + return *this += ACE_Time_Value (duration); } /// Assign @a std::duration to this @@ -291,11 +287,7 @@ class ACE_Export ACE_Time_Value template< class Rep, class Period > ACE_Time_Value &operator -= (const std::chrono::duration& duration) { - const ACE_Time_Value tv (duration); - this->sec (this->sec () - tv.sec ()); - this->usec (this->usec () - tv.usec ()); - this->normalize (); - return *this; + return *this -= ACE_Time_Value (duration); } /** diff --git a/ACE/tests/.gitignore b/ACE/tests/.gitignore index b4ba4f725ac68..7fd2adc39d19e 100644 --- a/ACE/tests/.gitignore +++ b/ACE/tests/.gitignore @@ -94,6 +94,13 @@ /Compiler_Features_33_Test /Compiler_Features_34_Test /Compiler_Features_35_Test +/Compiler_Features_36_Test +/Compiler_Features_37_Test +/Compiler_Features_38_Test +/Compiler_Features_39_Test +/Compiler_Features_40_Test +/Compiler_Features_41_Test +/Compiler_Features_42_Test /Config_Test /Conn_Test /Date_Time_Test @@ -110,6 +117,7 @@ /FlReactor_Test /Framework_Component_Test /Future_Set_Test +/Future_Stress_Test /Future_Test /Get_Opt_Test /Handle_Set_Test @@ -152,6 +160,7 @@ /MT_Reference_Counted_Event_Handler_Test /MT_Reference_Counted_Notify_Test /MT_SOCK_Test +/Multicast_Interfaces_Test /Multicast_Test /Multicast_Test_IPV6 /Multihomed_INET_Addr_Test @@ -216,8 +225,9 @@ /Signal_Test /Sigset_Ops_Test /Simple_Message_Block_Test -/Singleton_Test /Singleton_Restart_Test +/Singleton_Test +/SOCK_Acceptor_Test /SOCK_Connector_Test /SOCK_Dgram_Bcast_Test /SOCK_Dgram_Test @@ -256,8 +266,8 @@ /Token_Strategy_Test /Tokens_Test /TP_Reactor_Test -/TSS_Static_Test /TSS_Leak_Test +/TSS_Static_Test /TSS_Test /Unbounded_Set_Test /Unbounded_Set_Test_Ex @@ -273,8 +283,3 @@ /XtAthenaReactor_Test /XtMotifReactor_Test /XtReactor_Test -/Compiler_Features_36_Test -/Compiler_Features_37_Test -/Compiler_Features_38_Test -/SOCK_Acceptor_Test -Multicast_Interfaces_Test diff --git a/ACE/tests/Chrono_Test.cpp b/ACE/tests/Chrono_Test.cpp index 7a09b1d9a99d9..b8f28a5ffe7c5 100644 --- a/ACE/tests/Chrono_Test.cpp +++ b/ACE/tests/Chrono_Test.cpp @@ -21,132 +21,75 @@ #include "ace/Truncate.h" int -test_assignments () +tv_test_case (const ACE_Time_Value& tv, const char *what, time_t expect_sec, suseconds_t expect_usec = 0) { - int errors {}; - ACE_Time_Value tv { std::chrono::nanoseconds {100} }; - if (tv.sec () != 0 || tv.usec () != 0) + if (tv.sec () != expect_sec || tv.usec () != expect_usec) { ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::nanoseconds (100) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; + ACE_TEXT ("(%P|%t) unexpected value after converting %C to an ACE_Time_Value. ") + ACE_TEXT ("Expected - got \n"), + what, expect_sec, expect_usec, tv.sec (), tv.usec ())); + return 1; } + return 0; +} - tv = ACE_Time_Value { std::chrono::nanoseconds {10005} }; - if (tv.sec () != 0 || tv.usec () != 10) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::nanoseconds (10005) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } +template +int +tv_test_case (const std::chrono::duration& duration, + const char *what, time_t expect_sec, suseconds_t expect_usec = 0) +{ + return tv_test_case (ACE_Time_Value {duration}, what, expect_sec, expect_usec); +} - tv = ACE_Time_Value { std::chrono::microseconds {1} }; - if (tv.sec () != 0 || tv.usec () != 1) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::microseconds (1) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } +int +test_assignments () +{ + int errors {}; - tv = ACE_Time_Value { std::chrono::microseconds {10005} }; - if (tv.sec () != 0 || tv.usec () != 10005) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::microseconds (10005) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(std::chrono::nanoseconds {100}, "nanoseconds (100)", 0); - std::chrono::milliseconds ms_test { tv.msec () }; - if (ms_test.count () != 10) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after get_chrono_msec. ") - ACE_TEXT ("Expected <10> - got <%q>\n"), - ms_test.count ())); - ++errors; - } + errors += tv_test_case(std::chrono::nanoseconds {10005}, "nanoseconds (10005)", 0, 10); - tv = ACE_Time_Value { std::chrono::milliseconds {1} }; - if (tv.sec () != 0 || tv.usec () != 1000) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::milliseconds (1) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(std::chrono::microseconds {1}, "microseconds (1)", 0, 1); - tv = ACE_Time_Value { std::chrono::milliseconds {10005} }; - if (tv.sec () != 10 || tv.usec () != 5000) { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::milliseconds (10005) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } + ACE_Time_Value const tv = ACE_Time_Value { std::chrono::microseconds {10005} }; + errors += tv_test_case(tv, "microseconds (10005)", 0, 10005); - tv = ACE_Time_Value { std::chrono::seconds {1} }; - if (tv.sec () != 1 || tv.usec () != 0) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::seconds (1) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; + std::chrono::milliseconds ms_test { tv.msec () }; + if (ms_test.count () != 10) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) unexpected value after get_chrono_msec. ") + ACE_TEXT ("Expected <10> - got <%q>\n"), + ms_test.count ())); + ++errors; + } } - tv = ACE_Time_Value { std::chrono::seconds {10005} }; - if (tv.sec () != 10005 || tv.usec () != 0) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::seconds (10005) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(std::chrono::milliseconds {1}, "milliseconds (1)", 0, 1000); - tv = ACE_Time_Value { std::chrono::hours {1} }; - if (tv.sec () != 3600 || tv.usec () != 0) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::hours (1) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(std::chrono::milliseconds {10005}, "milliseconds (10005)", 10, 5000); - tv = ACE_Time_Value { std::chrono::hours {10005} }; - if (tv.sec () != 3600*10005 || tv.usec () != 0) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("std::chrono::hours (10005) to an ACE_Time_Value. ") - ACE_TEXT (" - got \n"), - 3600*10005, tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(std::chrono::seconds {1}, "seconds (1)", 1); + + errors += tv_test_case(std::chrono::seconds {10005}, "seconds (10005)", 10005); + + errors += tv_test_case(std::chrono::hours {1}, "hours (1)", 3600); + + errors += tv_test_case(std::chrono::hours {10005}, "hours (10005)", 3600*10005); + + // ACE_Time_Value should accept floating-point-based durations. + std::chrono::duration> const half_day {0.5}; + errors += tv_test_case(half_day, "duration>{0.5}", 3600*12, 0); + errors += tv_test_case(std::chrono::duration {0.1}, "duration{0.1}", 0, 100000); + errors += tv_test_case(std::chrono::duration {-0.1}, "duration{-0.1}", 0, -100000); + // It being -99,999 instead of -100,000 seems to be a IEEE 754 thing + errors += tv_test_case(std::chrono::duration {-10.1}, "duration{-10.1}", -10, -99999); // Two times half a day, 3 hours, 24 minutes, 54 seconds, 238 milliseconds, // 754 microseconds and 342 nanoseconds. - std::chrono::duration> half_day {0.5}; std::chrono::microseconds const usec { 2 * ( std::chrono::duration_cast ( @@ -156,36 +99,16 @@ test_assignments () std::chrono::microseconds {754} + std::chrono::nanoseconds {342})) }; - - tv = ACE_Time_Value {usec}; - // half a day 3 hours 24 minutes 54 seconds time_t expected_sec = { ((12*3600) + (3*3600) + (24*60) + 54 ) * 2 }; // 238 milli usec 342 nano suseconds_t expected_usec = { ((238*1000) + 754 + 0) * 2 }; + errors += tv_test_case(usec, + "two times half a day, 3 hours, 24 minutes, 54 seconds, " + "238 milliseconds, 754 microseconds and 342 nanoseconds", + expected_sec, expected_usec); - if (tv.sec () != expected_sec || tv.usec () != expected_usec) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("two times half a day, 3 hours, 24 minutes, 54 seconds, ") - ACE_TEXT ("238 milliseconds, 754 microseconds and 342 nanoseconds ") - ACE_TEXT ("to an ACE_Time_Value. Expected - ") - ACE_TEXT ("got \n"), - expected_sec, expected_usec, tv.sec (), tv.usec ())); - ++errors; - } - - tv.set (std::chrono::milliseconds {1120}); - if (tv.sec () != 1 || tv.usec () != 120 * std::kilo::num) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after converting ") - ACE_TEXT ("a std::chrono::milliseconds of 1120 to an ACE_Time_Value ") - ACE_TEXT ("Expected - got \n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(std::chrono::milliseconds {1120}, "milliseconds (1120)", 1, 120 * std::kilo::num); return errors; } From c9d1cbe79b740aae729273d0111d7deb3a8a8d99 Mon Sep 17 00:00:00 2001 From: Fred Hornsey Date: Wed, 3 Sep 2025 01:26:37 -0500 Subject: [PATCH 2/3] More Tweaks to Chrono_Test --- ACE/tests/Chrono_Test.cpp | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/ACE/tests/Chrono_Test.cpp b/ACE/tests/Chrono_Test.cpp index b8f28a5ffe7c5..5febaf66574bc 100644 --- a/ACE/tests/Chrono_Test.cpp +++ b/ACE/tests/Chrono_Test.cpp @@ -5,7 +5,6 @@ * * This is a test of the usage of 'std::chrono' throughout ACE * The following items are tested: - * - ACE_OS::sleep * - ACE_Time_Value * * @@ -301,29 +300,14 @@ test_ace_time_value_operators () std::chrono::duration_cast(sec) + std::chrono::duration_cast(usec) }; - ACE_Time_Value tv; tv = msec; tv += std::chrono::milliseconds {300}; - if (tv.sec () != 2 || tv.usec () != 303 * std::kilo::num) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after adding a duration ") - ACE_TEXT ("of 300 ms. Expected - got .\n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(tv, "seconds {2} + microseconds {3000} + milliseconds {300}", 2, 303 * std::kilo::num); + tv -= std::chrono::microseconds {400}; - if (tv.sec () != 2 || tv.usec () != 302600) - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) unexpected value after substracting a duration ") - ACE_TEXT ("of 400 us. Expected - got .\n"), - tv.sec (), tv.usec ())); - ++errors; - } + errors += tv_test_case(tv, "seconds {2} + microseconds {3000} + milliseconds {300} - microseconds {400}", 2, 302600 * std::kilo::num); + return errors; } From addc542381926016504cb3cd23464941848357ff Mon Sep 17 00:00:00 2001 From: Fred Hornsey Date: Wed, 3 Sep 2025 10:49:00 -0500 Subject: [PATCH 3/3] Fix Issues with Chrono Test --- ACE/tests/Chrono_Test.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ACE/tests/Chrono_Test.cpp b/ACE/tests/Chrono_Test.cpp index 5febaf66574bc..2b3358a5f2004 100644 --- a/ACE/tests/Chrono_Test.cpp +++ b/ACE/tests/Chrono_Test.cpp @@ -88,23 +88,22 @@ test_assignments () errors += tv_test_case(std::chrono::duration {-10.1}, "duration{-10.1}", -10, -99999); // Two times half a day, 3 hours, 24 minutes, 54 seconds, 238 milliseconds, - // 754 microseconds and 342 nanoseconds. - std::chrono::microseconds const usec { - 2 * ( - std::chrono::duration_cast ( + // 754 microseconds and 342 nanoseconds (lost). + std::chrono::nanoseconds const nsec { + 2 * std::chrono::duration_cast ( half_day + std::chrono::hours {3} + std::chrono::minutes {24} + std::chrono::seconds {54} + std::chrono::milliseconds {238} + - std::chrono::microseconds {754} + std::chrono::nanoseconds {342})) + std::chrono::microseconds {754} + std::chrono::nanoseconds {342}) }; // half a day 3 hours 24 minutes 54 seconds time_t expected_sec = { ((12*3600) + (3*3600) + (24*60) + 54 ) * 2 }; - // 238 milli usec 342 nano + // 238 milli 754 usec 342 nano (lost) suseconds_t expected_usec = { ((238*1000) + 754 + 0) * 2 }; - errors += tv_test_case(usec, + errors += tv_test_case(nsec, "two times half a day, 3 hours, 24 minutes, 54 seconds, " - "238 milliseconds, 754 microseconds and 342 nanoseconds", + "238 milliseconds, 754 microseconds and 342 nanoseconds (lost)", expected_sec, expected_usec); errors += tv_test_case(std::chrono::milliseconds {1120}, "milliseconds (1120)", 1, 120 * std::kilo::num); @@ -306,7 +305,7 @@ test_ace_time_value_operators () errors += tv_test_case(tv, "seconds {2} + microseconds {3000} + milliseconds {300}", 2, 303 * std::kilo::num); tv -= std::chrono::microseconds {400}; - errors += tv_test_case(tv, "seconds {2} + microseconds {3000} + milliseconds {300} - microseconds {400}", 2, 302600 * std::kilo::num); + errors += tv_test_case(tv, "seconds {2} + microseconds {3000} + milliseconds {300} - microseconds {400}", 2, 302600); return errors; }