summaryrefslogtreecommitdiff
path: root/src/mongo/util/duration.h
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2021-01-16 12:54:43 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-01-22 09:27:32 +0000
commit332df3bdd7e6d5f7f9a09c9bd0861f5370bc667c (patch)
tree8e6186b4036e44ff2b1e1b80bc3ac32dca51d5d6 /src/mongo/util/duration.h
parent760f6bc37313888fa755235a61d9962624c688f4 (diff)
downloadmongo-332df3bdd7e6d5f7f9a09c9bd0861f5370bc667c.tar.gz
SERVER-47709 add deduceChronoDuration to duration.h
Diffstat (limited to 'src/mongo/util/duration.h')
-rw-r--r--src/mongo/util/duration.h50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/mongo/util/duration.h b/src/mongo/util/duration.h
index ed187c0ed71..51b2eae14b6 100644
--- a/src/mongo/util/duration.h
+++ b/src/mongo/util/duration.h
@@ -30,10 +30,12 @@
#pragma once
#include <cstdint>
-#include <fmt/format.h>
#include <iosfwd>
#include <limits>
#include <ratio>
+#include <type_traits>
+
+#include <fmt/format.h>
#include "mongo/base/static_assert.h"
#include "mongo/platform/overflow_arithmetic.h"
@@ -60,6 +62,13 @@ using Minutes = Duration<std::ratio<60>>;
using Hours = Duration<std::ratio<3600>>;
using Days = Duration<std::ratio<86400>>;
+namespace duration_detail {
+template <typename>
+inline constexpr bool isMongoDuration = false;
+template <typename... Ts>
+inline constexpr bool isMongoDuration<Duration<Ts...>> = true;
+} // namespace duration_detail
+
//
// Streaming output operators for common duration types. Writes the numerical value followed by
// an abbreviated unit, without a space.
@@ -81,7 +90,9 @@ using HigherPrecisionDuration =
* the ToDuration. For example, Seconds::max() cannot be represented as a Milliseconds, and so
* attempting to cast that value to Milliseconds will throw an exception.
*/
-template <typename ToDuration, typename FromPeriod>
+template <typename ToDuration,
+ typename FromPeriod,
+ std::enable_if_t<duration_detail::isMongoDuration<ToDuration>, int> = 0>
constexpr ToDuration duration_cast(const Duration<FromPeriod>& from) {
using FromOverTo = std::ratio_divide<FromPeriod, typename ToDuration::period>;
if (ToDuration::template isHigherPrecisionThan<Duration<FromPeriod>>()) {
@@ -94,7 +105,10 @@ constexpr ToDuration duration_cast(const Duration<FromPeriod>& from) {
return ToDuration{from.count() / FromOverTo::den};
}
-template <typename ToDuration, typename FromRep, typename FromPeriod>
+template <typename ToDuration,
+ typename FromRep,
+ typename FromPeriod,
+ std::enable_if_t<duration_detail::isMongoDuration<ToDuration>, int> = 0>
constexpr ToDuration duration_cast(const stdx::chrono::duration<FromRep, FromPeriod>& d) {
return duration_cast<ToDuration>(Duration<FromPeriod>{d.count()});
}
@@ -488,4 +502,34 @@ StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Durat
return streamPut(os, dp);
}
+/**
+ * Make a std::chrono::duration from an arithmetic expression and a period ratio.
+ * This does not do any math or precision changes. It's just a type-deduced wrapper
+ * that attaches a period to a number for typesafety. The output std::chrono::duration
+ * will retain the Rep type and value of the input argument.
+ *
+ * E.g:
+ * int waited = 123; // unitless, type-unsafe millisecond count.
+ * auto dur = deduceChronoDuration<std::milli>(waited);
+ * static_assert(std::is_same_v<decltype(dur),
+ * std::chrono::duration<int, std::milli>>);
+ * invariant(dur.count() == 123);
+ *
+ * Note that std::chrono::duration<int, std::milli> is not std::milliseconds,
+ * which has a different (unspecified) Rep type.
+ *
+ * Then mongo::duration_cast can convert the deduced std::chrono::duration to
+ * mongo::Duration, or `std::chrono::duration_cast` be used to adjust the rep
+ * to create a more canonical std::chrono::duration:
+ *
+ * auto durMongo = duration_cast<Milliseconds>(dur);
+ * auto durChrono = duration_cast<std::milliseconds>(dur);
+ *
+ * Order the cast operations carefully to avoid losing range or precision.
+ */
+template <typename Per = std::ratio<1>, typename Rep>
+constexpr auto deduceChronoDuration(const Rep& count) {
+ return stdx::chrono::duration<Rep, Per>{count};
+}
+
} // namespace mongo