From 4d560848f1c3bd95f8aa338f1b38cae2cdb6d44e Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Sun, 18 Sep 2022 13:36:55 +0200 Subject: [PATCH] enhance: Add util::TimePoint and util::Duration --- src/util/Duration.hpp | 135 ++++++++++++++++++++++++ src/util/TimePoint.cpp | 35 +++++++ src/util/TimePoint.hpp | 175 +++++++++++++++++++++++++++++++ unittest/CMakeLists.txt | 1 + unittest/test_util_TimePoint.cpp | 132 +++++++++++++++++++++++ 5 files changed, 478 insertions(+) create mode 100644 src/util/Duration.hpp create mode 100644 src/util/TimePoint.cpp create mode 100644 src/util/TimePoint.hpp create mode 100644 unittest/test_util_TimePoint.cpp diff --git a/src/util/Duration.hpp b/src/util/Duration.hpp new file mode 100644 index 000000000..12c8729b6 --- /dev/null +++ b/src/util/Duration.hpp @@ -0,0 +1,135 @@ +// Copyright (C) 2022 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#pragma once + +#include + +namespace util { + +class Duration +{ +public: + explicit Duration(int64_t sec = 0, int64_t nsec = 0); + + bool operator==(const Duration& other) const; + bool operator!=(const Duration& other) const; + bool operator<(const Duration& other) const; + bool operator>(const Duration& other) const; + bool operator<=(const Duration& other) const; + bool operator>=(const Duration& other) const; + + Duration operator+(const Duration& other) const; + Duration operator-(const Duration& other) const; + Duration operator*(double factor) const; + Duration operator/(double factor) const; + + Duration operator-() const; + + int64_t sec() const; + int64_t nsec() const; + int32_t nsec_decimal_part() const; + +private: + int64_t m_ns = 0; +}; + +inline Duration::Duration(int64_t sec, int64_t nsec) + : m_ns(1'000'000'000 * sec + nsec) +{ +} + +inline bool +Duration::operator==(const Duration& other) const +{ + return m_ns == other.m_ns; +} + +inline bool +Duration::operator!=(const Duration& other) const +{ + return m_ns != other.m_ns; +} + +inline bool +Duration::operator<(const Duration& other) const +{ + return m_ns < other.m_ns; +} + +inline bool +Duration::operator>(const Duration& other) const +{ + return m_ns > other.m_ns; +} + +inline bool +Duration::operator<=(const Duration& other) const +{ + return m_ns <= other.m_ns; +} + +inline bool +Duration::operator>=(const Duration& other) const +{ + return m_ns >= other.m_ns; +} + +inline Duration +Duration::operator+(const Duration& other) const +{ + return Duration(m_ns + other.m_ns); +} + +inline Duration +Duration::operator-(const Duration& other) const +{ + return Duration(m_ns - other.m_ns); +} + +inline Duration +Duration::operator*(double factor) const +{ + return Duration(factor * m_ns); +} + +inline Duration +Duration::operator/(double factor) const +{ + return Duration(m_ns / factor); +} + +inline int64_t +Duration::sec() const +{ + return m_ns / 1'000'000'000; +} + +inline int64_t +Duration::nsec() const +{ + return m_ns; +} + +inline int32_t +Duration::nsec_decimal_part() const +{ + return m_ns % 1'000'000'000; +} + +} // namespace util diff --git a/src/util/TimePoint.cpp b/src/util/TimePoint.cpp new file mode 100644 index 000000000..db6016971 --- /dev/null +++ b/src/util/TimePoint.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include "TimePoint.hpp" + +#include + +namespace util { + +TimePoint +TimePoint::now() +{ + return TimePoint(0, + std::chrono::time_point_cast( + std::chrono::system_clock::now()) + .time_since_epoch() + .count()); +} + +} // namespace util diff --git a/src/util/TimePoint.hpp b/src/util/TimePoint.hpp new file mode 100644 index 000000000..9b5756daa --- /dev/null +++ b/src/util/TimePoint.hpp @@ -0,0 +1,175 @@ +// Copyright (C) 2022 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#pragma once + +#include + +#include +#include + +namespace util { + +class TimePoint +{ +public: + explicit TimePoint(int64_t sec = 0, int64_t nsec = 0); + TimePoint(const TimePoint& other); + explicit TimePoint(const timespec& timespec); + + TimePoint& operator=(const TimePoint& other); + + static TimePoint now(); + + timespec to_timespec() const; + + int64_t sec() const; + int64_t nsec() const; + int32_t nsec_decimal_part() const; + + void set_sec(int64_t sec, uint32_t nsec = 0); + void set_nsec(int64_t nsec); + + bool operator==(const TimePoint& other) const; + bool operator!=(const TimePoint& other) const; + bool operator<(const TimePoint& other) const; + bool operator>(const TimePoint& other) const; + bool operator<=(const TimePoint& other) const; + bool operator>=(const TimePoint& other) const; + + TimePoint operator+(const util::Duration& duration) const; + TimePoint operator-(const util::Duration& duration) const; + + util::Duration operator-(const TimePoint& other) const; + +private: + int64_t m_ns = 0; +}; + +inline TimePoint::TimePoint(int64_t sec, int64_t nsec) + : m_ns(1'000'000'000 * sec + nsec) +{ +} + +inline TimePoint::TimePoint(const TimePoint& other) : m_ns(other.m_ns) +{ +} + +inline TimePoint::TimePoint(const timespec& timespec) + : TimePoint(timespec.tv_sec, timespec.tv_nsec) +{ +} + +inline TimePoint& +TimePoint::operator=(const TimePoint& other) +{ + m_ns = other.m_ns; + return *this; +} + +inline timespec +TimePoint::to_timespec() const +{ + return {static_cast(sec()), nsec_decimal_part()}; +} + +inline int64_t +TimePoint::sec() const +{ + return m_ns / 1'000'000'000; +} + +inline int64_t +TimePoint::nsec() const +{ + return m_ns; +} + +inline int32_t +TimePoint::nsec_decimal_part() const +{ + return m_ns % 1'000'000'000; +} + +inline void +TimePoint::set_sec(int64_t sec, uint32_t nsec) +{ + m_ns = 1'000'000'000 * sec + nsec; +} + +inline void +TimePoint::set_nsec(int64_t nsec) +{ + m_ns = nsec; +} + +inline bool +TimePoint::operator==(const TimePoint& other) const +{ + return m_ns == other.m_ns; +} + +inline bool +TimePoint::operator!=(const TimePoint& other) const +{ + return m_ns != other.m_ns; +} + +inline bool +TimePoint::operator<(const TimePoint& other) const +{ + return m_ns < other.m_ns; +} + +inline bool +TimePoint::operator>(const TimePoint& other) const +{ + return m_ns > other.m_ns; +} + +inline bool +TimePoint::operator<=(const TimePoint& other) const +{ + return m_ns <= other.m_ns; +} + +inline bool +TimePoint::operator>=(const TimePoint& other) const +{ + return m_ns >= other.m_ns; +} + +inline TimePoint +TimePoint::operator+(const util::Duration& duration) const +{ + return TimePoint(0, nsec() + duration.nsec()); +} + +inline TimePoint +TimePoint::operator-(const util::Duration& duration) const +{ + return TimePoint(0, nsec() - duration.nsec()); +} + +inline util::Duration +TimePoint::operator-(const TimePoint& other) const +{ + return util::Duration(0, nsec() - other.nsec()); +} + +} // namespace util diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 5c5ab65d5..854d41cbe 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -22,6 +22,7 @@ set( test_util_Bytes.cpp test_util_LockFile.cpp test_util_TextTable.cpp + test_util_TimePoint.cpp test_util_Tokenizer.cpp test_util_XXH3_128.cpp test_util_XXH3_64.cpp diff --git a/unittest/test_util_TimePoint.cpp b/unittest/test_util_TimePoint.cpp new file mode 100644 index 000000000..33f1bded1 --- /dev/null +++ b/unittest/test_util_TimePoint.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2022 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include + +#include + +TEST_SUITE_BEGIN("util::TimePoint"); + +using util::TimePoint; + +TEST_CASE("Basics") +{ + TimePoint t0(4711, 2042); + + CHECK(t0.sec() == 4711); + CHECK(t0.nsec() == 4711000002042); +} + +TEST_CASE("Conversions") +{ + TimePoint t0(4711, 2042); + + SUBCASE("to_timespec") + { + timespec ts = t0.to_timespec(); + CHECK(ts.tv_sec == 4711); + CHECK(ts.tv_nsec == 2042); + } +} + +TEST_CASE("Comparison operators") +{ + TimePoint t0(1000, 0); + TimePoint t1(1000, 42); + TimePoint t2(1001, 0); + + SUBCASE("operator==") + { + CHECK(t0 == t0); + CHECK(!(t0 == t1)); + CHECK(!(t1 == t0)); + CHECK(!(t0 == t2)); + CHECK(!(t2 == t0)); + } + + SUBCASE("operator!=") + { + CHECK(!(t0 != t0)); + CHECK(t0 != t1); + CHECK(t1 != t0); + } + + SUBCASE("operator<") + { + CHECK(t0 < t1); + CHECK(t0 < t2); + CHECK(t1 < t2); + CHECK(!(t1 < t0)); + CHECK(!(t2 < t0)); + CHECK(!(t2 < t1)); + } + + SUBCASE("operator>") + { + CHECK(t2 > t1); + CHECK(t2 > t0); + CHECK(t1 > t0); + CHECK(!(t1 > t2)); + CHECK(!(t0 > t2)); + CHECK(!(t0 > t1)); + } + + SUBCASE("operator<=") + { + CHECK(t0 <= t0); + CHECK(t0 <= t1); + CHECK(t0 <= t2); + CHECK(!(t1 <= t0)); + CHECK(!(t2 <= t0)); + } + + SUBCASE("operator>=") + { + CHECK(t2 >= t1); + CHECK(t2 >= t0); + CHECK(t1 >= t0); + CHECK(!(t1 >= t2)); + CHECK(!(t0 >= t2)); + } +} + +TEST_CASE("Operations with duration") +{ + TimePoint t0(1, 2); + TimePoint t1(3, 17); + + SUBCASE("operator-(TimePoint)") + { + CHECK(t1 - t0 == util::Duration(2, 15)); + CHECK(t0 - t1 == util::Duration(-2, -15)); + } + + SUBCASE("operator+(Duration)") + { + CHECK(t0 + util::Duration(4, 999999999) == util::TimePoint(6, 1)); + } + + SUBCASE("operator-(Duration))") + { + auto t = t0 - util::Duration(4, 999999999); + CHECK(t.sec() == -3); + CHECK(t.nsec_decimal_part() == -999999997); + } +} + +TEST_SUITE_END(); -- 2.47.2