aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@yahooinc.com>2023-02-07 15:28:56 +0000
committerHåvard Pettersen <havardpe@yahooinc.com>2023-02-07 15:38:26 +0000
commit70109fabff7e72d74de205322c8a4dde134e4df0 (patch)
tree72c59b84bc8c18c3ace0f3603b606d76a6b6aaf5 /vespalib
parent880182fec33634bec6bbfa9c0f1a2b85e4e1f8f2 (diff)
added utility function for saturated add
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/time/time_test.cpp22
-rw-r--r--vespalib/src/vespa/vespalib/util/time.cpp13
-rw-r--r--vespalib/src/vespa/vespalib/util/time.h2
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.