diff options
author | Håvard Pettersen <havardpe@yahooinc.com> | 2023-02-07 15:28:56 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@yahooinc.com> | 2023-02-07 15:38:26 +0000 |
commit | 70109fabff7e72d74de205322c8a4dde134e4df0 (patch) | |
tree | 72c59b84bc8c18c3ace0f3603b606d76a6b6aaf5 /vespalib | |
parent | 880182fec33634bec6bbfa9c0f1a2b85e4e1f8f2 (diff) |
added utility function for saturated add
Diffstat (limited to 'vespalib')
-rw-r--r-- | vespalib/src/tests/time/time_test.cpp | 22 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/time.cpp | 13 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/time.h | 2 |
3 files changed, 37 insertions, 0 deletions
diff --git a/vespalib/src/tests/time/time_test.cpp b/vespalib/src/tests/time/time_test.cpp index 0ca583c8326..f5738611a41 100644 --- a/vespalib/src/tests/time/time_test.cpp +++ b/vespalib/src/tests/time/time_test.cpp @@ -5,6 +5,7 @@ #include <cinttypes> #include <thread> #include <atomic> +#include <iostream> using namespace vespalib; @@ -83,4 +84,25 @@ TEST(TimeTest, timeout_is_relative_to_frequency) { EXPECT_EQ(2000ms, adjustTimeoutByHz(20ms, 10)); } +TEST(TimeTest, print_limits) { + std::cerr << "steady_time::min().time_since_epoch(): " << steady_time::min().time_since_epoch() << "\n"; + std::cerr << "steady_time::max().time_since_epoch(): " << steady_time::max().time_since_epoch() << "\n"; + std::cerr << "duration::min(): " << duration::min() << "\n"; + std::cerr << "duration::max(): " << duration::max() << "\n"; +} + +TEST(TimeTest, saturated_add_without_overflow) { + steady_time time_10ms(10ms); + steady_time time_20ms(20ms); + EXPECT_EQ(saturated_add(time_10ms, 10ms), time_20ms); + EXPECT_EQ(saturated_add(time_20ms, -10ms), time_10ms); +} + +TEST(TimeTest, saturated_add_with_overflow) { + steady_time future(1000000000s); + steady_time past(-1000000000s); + EXPECT_EQ(saturated_add(future, duration::max()), steady_time::max()); + EXPECT_EQ(saturated_add(past, duration::min()), steady_time::min()); +} + GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/vespa/vespalib/util/time.cpp b/vespalib/src/vespa/vespalib/util/time.cpp index 3737a25f268..2dbaade8c0a 100644 --- a/vespalib/src/vespa/vespalib/util/time.cpp +++ b/vespalib/src/vespa/vespalib/util/time.cpp @@ -62,6 +62,19 @@ to_string(system_time time) { return to_string(time.time_since_epoch()); } +steady_time saturated_add(steady_time time, duration diff) { + auto td = time.time_since_epoch(); + using dur_t = decltype(td); + using val_t = dur_t::rep; + val_t a = td.count(); + val_t b = std::chrono::duration_cast<dur_t>(diff).count(); + val_t res; + if (__builtin_add_overflow(a, b, &res)) { + return (b > 0) ? steady_time::max() : steady_time::min(); + } + return steady_time(dur_t(res)); +} + Timer::~Timer() = default; void diff --git a/vespalib/src/vespa/vespalib/util/time.h b/vespalib/src/vespa/vespalib/util/time.h index 2355b269fa5..ce914b097d4 100644 --- a/vespalib/src/vespa/vespalib/util/time.h +++ b/vespalib/src/vespa/vespalib/util/time.h @@ -73,6 +73,8 @@ constexpr duration from_timespec(const timespec & ts) { vespalib::string to_string(system_time time); +steady_time saturated_add(steady_time time, duration diff); + /** * Simple utility class used to measure how much time has elapsed * since it was constructed. |