forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import FXL timing utilities into FML. (flutter#5311)
- Loading branch information
1 parent
fbf07dc
commit 99a1dde
Showing
8 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FML_TIME_TIME_DELTA_H_ | ||
#define FLUTTER_FML_TIME_TIME_DELTA_H_ | ||
|
||
#include <stdint.h> | ||
#include <time.h> | ||
|
||
#include <iosfwd> | ||
#include <limits> | ||
|
||
namespace fml { | ||
|
||
// A TimeDelta represents the difference between two time points. | ||
class TimeDelta { | ||
public: | ||
constexpr TimeDelta() = default; | ||
|
||
static constexpr TimeDelta Zero() { return TimeDelta(); } | ||
static constexpr TimeDelta Min() { | ||
return TimeDelta(std::numeric_limits<int64_t>::min()); | ||
} | ||
static constexpr TimeDelta Max() { | ||
return TimeDelta(std::numeric_limits<int64_t>::max()); | ||
} | ||
static constexpr TimeDelta FromNanoseconds(int64_t nanos) { | ||
return TimeDelta(nanos); | ||
} | ||
static constexpr TimeDelta FromMicroseconds(int64_t micros) { | ||
return FromNanoseconds(micros * 1000); | ||
} | ||
static constexpr TimeDelta FromMilliseconds(int64_t millis) { | ||
return FromMicroseconds(millis * 1000); | ||
} | ||
static constexpr TimeDelta FromSeconds(int64_t seconds) { | ||
return FromMilliseconds(seconds * 1000); | ||
} | ||
|
||
static constexpr TimeDelta FromSecondsF(double seconds) { | ||
return FromNanoseconds(seconds * (1000.0 * 1000.0 * 1000.0)); | ||
} | ||
|
||
constexpr int64_t ToNanoseconds() const { return delta_; } | ||
constexpr int64_t ToMicroseconds() const { return ToNanoseconds() / 1000; } | ||
constexpr int64_t ToMilliseconds() const { return ToMicroseconds() / 1000; } | ||
constexpr int64_t ToSeconds() const { return ToMilliseconds() / 1000; } | ||
|
||
constexpr double ToNanosecondsF() const { return delta_; } | ||
constexpr double ToMicrosecondsF() const { return delta_ / 1000.0; } | ||
constexpr double ToMillisecondsF() const { | ||
return delta_ / (1000.0 * 1000.0); | ||
} | ||
constexpr double ToSecondsF() const { | ||
return delta_ / (1000.0 * 1000.0 * 1000.0); | ||
} | ||
|
||
constexpr TimeDelta operator-(TimeDelta other) const { | ||
return TimeDelta::FromNanoseconds(delta_ - other.delta_); | ||
} | ||
|
||
constexpr TimeDelta operator+(TimeDelta other) const { | ||
return TimeDelta::FromNanoseconds(delta_ + other.delta_); | ||
} | ||
|
||
constexpr TimeDelta operator/(int64_t divisor) const { | ||
return TimeDelta::FromNanoseconds(delta_ / divisor); | ||
} | ||
|
||
constexpr int64_t operator/(TimeDelta other) const { | ||
return delta_ / other.delta_; | ||
} | ||
|
||
constexpr TimeDelta operator*(int64_t multiplier) const { | ||
return TimeDelta::FromNanoseconds(delta_ * multiplier); | ||
} | ||
|
||
constexpr TimeDelta operator%(TimeDelta other) const { | ||
return TimeDelta::FromNanoseconds(delta_ % other.delta_); | ||
} | ||
|
||
bool operator==(TimeDelta other) const { return delta_ == other.delta_; } | ||
bool operator!=(TimeDelta other) const { return delta_ != other.delta_; } | ||
bool operator<(TimeDelta other) const { return delta_ < other.delta_; } | ||
bool operator<=(TimeDelta other) const { return delta_ <= other.delta_; } | ||
bool operator>(TimeDelta other) const { return delta_ > other.delta_; } | ||
bool operator>=(TimeDelta other) const { return delta_ >= other.delta_; } | ||
|
||
static constexpr TimeDelta FromTimespec(struct timespec ts) { | ||
return TimeDelta::FromSeconds(ts.tv_sec) + | ||
TimeDelta::FromNanoseconds(ts.tv_nsec); | ||
} | ||
struct timespec ToTimespec() { | ||
struct timespec ts; | ||
constexpr int64_t kNanosecondsPerSecond = 1000000000ll; | ||
ts.tv_sec = static_cast<time_t>(ToSeconds()); | ||
ts.tv_nsec = delta_ % kNanosecondsPerSecond; | ||
return ts; | ||
} | ||
|
||
private: | ||
// Private, use one of the FromFoo() types | ||
explicit constexpr TimeDelta(int64_t delta) : delta_(delta) {} | ||
|
||
int64_t delta_ = 0; | ||
}; | ||
|
||
} // namespace fml | ||
|
||
#endif // FLUTTER_FML_TIME_TIME_DELTA_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright 2017 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/fml/time/time_delta.h" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
namespace fml { | ||
namespace { | ||
|
||
TEST(TimeDelta, Control) { | ||
EXPECT_LT(TimeDelta::Min(), TimeDelta::Zero()); | ||
EXPECT_GT(TimeDelta::Max(), TimeDelta::Zero()); | ||
|
||
EXPECT_GT(TimeDelta::Zero(), TimeDelta::FromMilliseconds(-100)); | ||
EXPECT_LT(TimeDelta::Zero(), TimeDelta::FromMilliseconds(100)); | ||
|
||
EXPECT_EQ(TimeDelta::FromMilliseconds(1000), TimeDelta::FromSeconds(1)); | ||
} | ||
|
||
} // namespace | ||
} // namespace fml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/fml/time/time_point.h" | ||
|
||
#include "flutter/fml/build_config.h" | ||
|
||
#if defined(OS_MACOSX) || defined(OS_IOS) | ||
#include <mach/kern_return.h> | ||
#include <mach/mach_time.h> | ||
#elif defined(OS_FUCHSIA) | ||
#include <zircon/syscalls.h> | ||
#elif defined(OS_WIN) | ||
#include <windows.h> | ||
#else | ||
#include <time.h> | ||
#endif // defined(OS_MACOSX) || defined(OS_IOS) | ||
|
||
#include "flutter/fml/logging.h" | ||
|
||
namespace fml { | ||
|
||
// Mac OS X/iOS don't have a (useful) |clock_gettime()|. | ||
// Note: Chromium's |base::TimeTicks::Now()| uses boot time (obtained via | ||
// |sysctl()| with |CTL_KERN|/|KERN_BOOTTIME|). For our current purposes, | ||
// monotonic time (which pauses during sleeps) is sufficient. TODO(vtl): If/when | ||
// we use this for other purposes, maybe we should use boot time (maybe also on | ||
// POSIX). | ||
#if defined(OS_MACOSX) || defined(OS_IOS) | ||
|
||
mach_timebase_info_data_t GetMachTimebaseInfo() { | ||
mach_timebase_info_data_t timebase_info = {}; | ||
kern_return_t error = mach_timebase_info(&timebase_info); | ||
FML_DCHECK(error == KERN_SUCCESS); | ||
return timebase_info; | ||
} | ||
|
||
// static | ||
TimePoint TimePoint::Now() { | ||
static mach_timebase_info_data_t timebase_info = GetMachTimebaseInfo(); | ||
return TimePoint(mach_absolute_time() * timebase_info.numer / | ||
timebase_info.denom); | ||
} | ||
|
||
#elif defined(OS_FUCHSIA) | ||
|
||
// static | ||
TimePoint TimePoint::Now() { | ||
return TimePoint(zx_clock_get(ZX_CLOCK_MONOTONIC)); | ||
} | ||
|
||
#elif defined(OS_WIN) | ||
|
||
TimePoint TimePoint::Now() { | ||
uint64_t freq = 0; | ||
uint64_t count = 0; | ||
QueryPerformanceFrequency((LARGE_INTEGER*)&freq); | ||
QueryPerformanceCounter((LARGE_INTEGER*)&count); | ||
return TimePoint((count * 1000000000) / freq); | ||
} | ||
|
||
#else | ||
|
||
// static | ||
TimePoint TimePoint::Now() { | ||
struct timespec ts; | ||
int res = clock_gettime(CLOCK_MONOTONIC, &ts); | ||
FML_DCHECK(res == 0); | ||
(void)res; | ||
return TimePoint::FromEpochDelta(TimeDelta::FromTimespec(ts)); | ||
} | ||
|
||
#endif // defined(OS_MACOSX) || defined(OS_IOS) | ||
|
||
} // namespace fml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FML_TIME_TIME_POINT_H_ | ||
#define FLUTTER_FML_TIME_TIME_POINT_H_ | ||
|
||
#include <stdint.h> | ||
|
||
#include <iosfwd> | ||
|
||
#include "flutter/fml/time/time_delta.h" | ||
|
||
namespace fml { | ||
|
||
// A TimePoint represents a point in time represented as an integer number of | ||
// nanoseconds elapsed since an arbitrary point in the past. | ||
// | ||
// WARNING: This class should not be serialized across reboots, or across | ||
// devices: the reference point is only stable for a given device between | ||
// reboots. | ||
class TimePoint { | ||
public: | ||
// Default TimePoint with internal value 0 (epoch). | ||
constexpr TimePoint() = default; | ||
|
||
static TimePoint Now(); | ||
|
||
static constexpr TimePoint Min() { | ||
return TimePoint(std::numeric_limits<int64_t>::min()); | ||
} | ||
|
||
static constexpr TimePoint Max() { | ||
return TimePoint(std::numeric_limits<int64_t>::max()); | ||
} | ||
|
||
static constexpr TimePoint FromEpochDelta(TimeDelta ticks) { | ||
return TimePoint(ticks.ToNanoseconds()); | ||
} | ||
|
||
TimeDelta ToEpochDelta() const { return TimeDelta::FromNanoseconds(ticks_); } | ||
|
||
// Compute the difference between two time points. | ||
TimeDelta operator-(TimePoint other) const { | ||
return TimeDelta::FromNanoseconds(ticks_ - other.ticks_); | ||
} | ||
|
||
TimePoint operator+(TimeDelta duration) const { | ||
return TimePoint(ticks_ + duration.ToNanoseconds()); | ||
} | ||
TimePoint operator-(TimeDelta duration) const { | ||
return TimePoint(ticks_ - duration.ToNanoseconds()); | ||
} | ||
|
||
bool operator==(TimePoint other) const { return ticks_ == other.ticks_; } | ||
bool operator!=(TimePoint other) const { return ticks_ != other.ticks_; } | ||
bool operator<(TimePoint other) const { return ticks_ < other.ticks_; } | ||
bool operator<=(TimePoint other) const { return ticks_ <= other.ticks_; } | ||
bool operator>(TimePoint other) const { return ticks_ > other.ticks_; } | ||
bool operator>=(TimePoint other) const { return ticks_ >= other.ticks_; } | ||
|
||
private: | ||
explicit constexpr TimePoint(int64_t ticks) : ticks_(ticks) {} | ||
|
||
int64_t ticks_ = 0; | ||
}; | ||
|
||
} // namespace fml | ||
|
||
#endif // FLUTTER_FML_TIME_TIME_POINT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2017 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/fml/time/time_point.h" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
namespace fml { | ||
namespace { | ||
|
||
TEST(TimePoint, Control) { | ||
EXPECT_LT(TimePoint::Min(), TimePoint::Now()); | ||
EXPECT_GT(TimePoint::Max(), TimePoint::Now()); | ||
} | ||
|
||
} // namespace | ||
} // namespace fml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include <thread> | ||
|
||
#include "flutter/fml/time/time_delta.h" | ||
#include "flutter/fml/time/time_point.h" | ||
#include "gtest/gtest.h" | ||
|
||
namespace fml { | ||
namespace { | ||
|
||
TEST(Time, Now) { | ||
auto start = TimePoint::Now(); | ||
for (int i = 0; i < 3; ++i) { | ||
auto now = TimePoint::Now(); | ||
EXPECT_GE(now, start); | ||
std::this_thread::yield(); | ||
} | ||
} | ||
|
||
TEST(Time, IntConversions) { | ||
// Integer conversions should all truncate, not round. | ||
TimeDelta delta = TimeDelta::FromNanoseconds(102304506708ll); | ||
EXPECT_EQ(102304506708ll, delta.ToNanoseconds()); | ||
EXPECT_EQ(102304506ll, delta.ToMicroseconds()); | ||
EXPECT_EQ(102304ll, delta.ToMilliseconds()); | ||
EXPECT_EQ(102ll, delta.ToSeconds()); | ||
} | ||
|
||
TEST(Time, FloatConversions) { | ||
// Float conversions should remain close to the original value. | ||
TimeDelta delta = TimeDelta::FromNanoseconds(102304506708ll); | ||
EXPECT_FLOAT_EQ(102304506708.0, delta.ToNanosecondsF()); | ||
EXPECT_FLOAT_EQ(102304506.708, delta.ToMicrosecondsF()); | ||
EXPECT_FLOAT_EQ(102304.506708, delta.ToMillisecondsF()); | ||
EXPECT_FLOAT_EQ(102.304506708, delta.ToSecondsF()); | ||
} | ||
|
||
TEST(Time, TimespecConversions) { | ||
struct timespec ts; | ||
ts.tv_sec = 5; | ||
ts.tv_nsec = 7; | ||
TimeDelta from_timespec = TimeDelta::FromTimespec(ts); | ||
EXPECT_EQ(5, from_timespec.ToSeconds()); | ||
EXPECT_EQ(5 * 1000000000ll + 7, from_timespec.ToNanoseconds()); | ||
struct timespec to_timespec = from_timespec.ToTimespec(); | ||
EXPECT_EQ(ts.tv_sec, to_timespec.tv_sec); | ||
EXPECT_EQ(ts.tv_nsec, to_timespec.tv_nsec); | ||
} | ||
|
||
} // namespace | ||
} // namespace fml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters