dcsctp: Add operators on TimeMs and DurationMs

To be able to use them type-safely, they should support native
operators (e.g. adding a time and a duration, or subtracting two time
values), as the alternative is to manage them as numbers.

Yes, this makes them behave a bit like absl::Time/absl::Duration.

Bug: webrtc:12614
Change-Id: I4dea12e33698a46e71fb549f44c06f2f381c9201
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/215143
Reviewed-by: Tommi <tommi@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33725}
This commit is contained in:
Victor Boivie 2021-04-13 14:52:53 +02:00 committed by Commit Bot
parent 8181b4f1e0
commit 9861f960c3
5 changed files with 126 additions and 6 deletions

View File

@ -46,11 +46,15 @@ if (rtc_include_tests) {
deps = [
":strong_alias",
":types",
"../../../rtc_base:checks",
"../../../rtc_base:gunit_helpers",
"../../../rtc_base:rtc_base_approved",
"../../../test:test_support",
]
sources = [ "strong_alias_test.cc" ]
sources = [
"strong_alias_test.cc",
"types_test.cc",
]
}
}

View File

@ -11,6 +11,8 @@
#ifndef NET_DCSCTP_PUBLIC_TYPES_H_
#define NET_DCSCTP_PUBLIC_TYPES_H_
#include <cstdint>
#include "net/dcsctp/public/strong_alias.h"
namespace dcsctp {
@ -29,10 +31,74 @@ using TimeoutID = StrongAlias<class TimeoutTag, uint64_t>;
using IsUnordered = StrongAlias<class IsUnorderedTag, bool>;
// Duration, as milliseconds. Overflows after 24 days.
using DurationMs = StrongAlias<class DurationMsTag, int32_t>;
class DurationMs : public StrongAlias<class DurationMsTag, int32_t> {
public:
constexpr explicit DurationMs(const UnderlyingType& v)
: StrongAlias<class DurationMsTag, int32_t>(v) {}
// Current time, in milliseconds since a client-defined epoch.´
using TimeMs = StrongAlias<class TimeMsTag, int64_t>;
// Convenience methods for working with time.
constexpr DurationMs& operator+=(DurationMs d) {
value_ += d.value_;
return *this;
}
constexpr DurationMs& operator-=(DurationMs d) {
value_ -= d.value_;
return *this;
}
template <typename T>
constexpr DurationMs& operator*=(T factor) {
value_ *= factor;
return *this;
}
};
constexpr inline DurationMs operator+(DurationMs lhs, DurationMs rhs) {
return lhs += rhs;
}
constexpr inline DurationMs operator-(DurationMs lhs, DurationMs rhs) {
return lhs -= rhs;
}
template <typename T>
constexpr inline DurationMs operator*(DurationMs lhs, T rhs) {
return lhs *= rhs;
}
template <typename T>
constexpr inline DurationMs operator*(T lhs, DurationMs rhs) {
return rhs *= lhs;
}
constexpr inline int32_t operator/(DurationMs lhs, DurationMs rhs) {
return lhs.value() / rhs.value();
}
// Represents time, in milliseconds since a client-defined epoch.
class TimeMs : public StrongAlias<class TimeMsTag, int64_t> {
public:
constexpr explicit TimeMs(const UnderlyingType& v)
: StrongAlias<class TimeMsTag, int64_t>(v) {}
// Convenience methods for working with time.
constexpr TimeMs& operator+=(DurationMs d) {
value_ += *d;
return *this;
}
constexpr TimeMs& operator-=(DurationMs d) {
value_ -= *d;
return *this;
}
};
constexpr inline TimeMs operator+(TimeMs lhs, DurationMs rhs) {
return lhs += rhs;
}
constexpr inline TimeMs operator+(DurationMs lhs, TimeMs rhs) {
return rhs += lhs;
}
constexpr inline TimeMs operator-(TimeMs lhs, DurationMs rhs) {
return lhs -= rhs;
}
constexpr inline DurationMs operator-(TimeMs lhs, TimeMs rhs) {
return DurationMs(*lhs - *rhs);
}
} // namespace dcsctp

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "net/dcsctp/public/types.h"
#include "rtc_base/gunit.h"
#include "test/gmock.h"
namespace dcsctp {
namespace {
TEST(TypesTest, DurationOperators) {
DurationMs d1(10);
DurationMs d2(25);
EXPECT_EQ(d1 + d2, DurationMs(35));
EXPECT_EQ(d2 - d1, DurationMs(15));
d1 += d2;
EXPECT_EQ(d1, DurationMs(35));
d1 -= DurationMs(5);
EXPECT_EQ(d1, DurationMs(30));
d1 *= 1.5;
EXPECT_EQ(d1, DurationMs(45));
EXPECT_EQ(DurationMs(10) * 2, DurationMs(20));
}
TEST(TypesTest, TimeOperators) {
EXPECT_EQ(TimeMs(250) + DurationMs(100), TimeMs(350));
EXPECT_EQ(DurationMs(250) + TimeMs(100), TimeMs(350));
EXPECT_EQ(TimeMs(250) - DurationMs(100), TimeMs(150));
EXPECT_EQ(TimeMs(250) - TimeMs(100), DurationMs(150));
TimeMs t1(150);
t1 -= DurationMs(50);
EXPECT_EQ(t1, TimeMs(100));
t1 += DurationMs(200);
EXPECT_EQ(t1, TimeMs(300));
}
} // namespace
} // namespace dcsctp

View File

@ -33,7 +33,7 @@ class FakeTimeout : public Timeout {
void Start(DurationMs duration_ms, TimeoutID timeout_id) override {
timeout_id_ = timeout_id;
expiry_ = TimeMs(*get_time_() + *duration_ms);
expiry_ = get_time_() + duration_ms;
}
void Stop() override { expiry_ = InfiniteFuture(); }

View File

@ -30,7 +30,7 @@ class TimerTest : public testing::Test {
}
void AdvanceTimeAndRunTimers(DurationMs duration) {
now_ = TimeMs(*now_ + *duration);
now_ = now_ + duration;
for (TimeoutID timeout_id : timeout_manager_.RunTimers()) {
manager_.HandleTimeout(timeout_id);