mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Import FXL timing utilities into FML. (flutter/engine#5311)
This commit is contained in:
parent
16bc51e056
commit
93b02cf2f9
@ -39,6 +39,9 @@ source_set("fml") {
|
||||
"thread.cc",
|
||||
"thread.h",
|
||||
"thread_local.h",
|
||||
"time/time_delta.h",
|
||||
"time/time_point.cc",
|
||||
"time/time_point.h",
|
||||
"trace_event.cc",
|
||||
"trace_event.h",
|
||||
"unique_fd.cc",
|
||||
@ -148,6 +151,9 @@ executable("fml_unittests") {
|
||||
"message_loop_unittests.cc",
|
||||
"thread_local_unittests.cc",
|
||||
"thread_unittests.cc",
|
||||
"time/time_delta_unittest.cc",
|
||||
"time/time_point_unittest.cc",
|
||||
"time/time_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
|
||||
111
engine/src/flutter/fml/time/time_delta.h
Normal file
111
engine/src/flutter/fml/time/time_delta.h
Normal file
@ -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_
|
||||
23
engine/src/flutter/fml/time/time_delta_unittest.cc
Normal file
23
engine/src/flutter/fml/time/time_delta_unittest.cc
Normal file
@ -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
|
||||
76
engine/src/flutter/fml/time/time_point.cc
Normal file
76
engine/src/flutter/fml/time/time_point.cc
Normal file
@ -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
|
||||
70
engine/src/flutter/fml/time/time_point.h
Normal file
70
engine/src/flutter/fml/time/time_point.h
Normal file
@ -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_
|
||||
18
engine/src/flutter/fml/time/time_point_unittest.cc
Normal file
18
engine/src/flutter/fml/time/time_point_unittest.cc
Normal file
@ -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
|
||||
54
engine/src/flutter/fml/time/time_unittest.cc
Normal file
54
engine/src/flutter/fml/time/time_unittest.cc
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user