TimePoint::Now uses DartTimestampProvider (#27737)
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 22347dc..9a1fc03 100755
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -292,6 +292,8 @@
FILE: ../../../flutter/fml/thread_unittests.cc
FILE: ../../../flutter/fml/time/chrono_timestamp_provider.cc
FILE: ../../../flutter/fml/time/chrono_timestamp_provider.h
+FILE: ../../../flutter/fml/time/dart_timestamp_provider.cc
+FILE: ../../../flutter/fml/time/dart_timestamp_provider.h
FILE: ../../../flutter/fml/time/time_delta.h
FILE: ../../../flutter/fml/time/time_delta_unittest.cc
FILE: ../../../flutter/fml/time/time_point.cc
diff --git a/fml/BUILD.gn b/fml/BUILD.gn
index 2f9964a..ff05896 100644
--- a/fml/BUILD.gn
+++ b/fml/BUILD.gn
@@ -77,6 +77,8 @@
"thread.h",
"thread_local.cc",
"thread_local.h",
+ "time/dart_timestamp_provider.cc",
+ "time/dart_timestamp_provider.h",
"time/time_delta.h",
"time/time_point.cc",
"time/time_point.h",
diff --git a/fml/time/chrono_timestamp_provider.cc b/fml/time/chrono_timestamp_provider.cc
index 5d315fd..b6e8efd 100644
--- a/fml/time/chrono_timestamp_provider.cc
+++ b/fml/time/chrono_timestamp_provider.cc
@@ -6,8 +6,6 @@
#include <chrono>
-#include "fml/time/time_delta.h"
-
namespace fml {
ChronoTimestampProvider::ChronoTimestampProvider() = default;
diff --git a/fml/time/chrono_timestamp_provider.h b/fml/time/chrono_timestamp_provider.h
index 0a03f36..bd0e6dd 100644
--- a/fml/time/chrono_timestamp_provider.h
+++ b/fml/time/chrono_timestamp_provider.h
@@ -8,7 +8,7 @@
#include "flutter/fml/time/timestamp_provider.h"
#include "flutter/fml/macros.h"
-#include "fml/time/time_point.h"
+#include "flutter/fml/time/time_point.h"
namespace fml {
diff --git a/fml/time/dart_timestamp_provider.cc b/fml/time/dart_timestamp_provider.cc
new file mode 100644
index 0000000..2c5de9d
--- /dev/null
+++ b/fml/time/dart_timestamp_provider.cc
@@ -0,0 +1,38 @@
+// Copyright 2013 The Flutter 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/dart_timestamp_provider.h"
+
+#include "dart_tools_api.h"
+
+namespace fml {
+
+DartTimestampProvider::DartTimestampProvider() = default;
+
+DartTimestampProvider::~DartTimestampProvider() = default;
+
+int64_t DartTimestampProvider::ConvertToNanos(int64_t ticks,
+ int64_t frequency) {
+ int64_t nano_seconds = (ticks / frequency) * kNanosPerSecond;
+ int64_t leftover_ticks = ticks % frequency;
+ int64_t leftover_nanos = (leftover_ticks * kNanosPerSecond) / frequency;
+ return nano_seconds + leftover_nanos;
+}
+
+fml::TimePoint DartTimestampProvider::Now() {
+ const int64_t ticks = Dart_TimelineGetTicks();
+ const int64_t frequency = Dart_TimelineGetTicksFrequency();
+ // optimization for the most common case.
+ if (frequency != kNanosPerSecond) {
+ return fml::TimePoint::FromTicks(ConvertToNanos(ticks, frequency));
+ } else {
+ return fml::TimePoint::FromTicks(ticks);
+ }
+}
+
+fml::TimePoint DartTimelineTicksSinceEpoch() {
+ return DartTimestampProvider::Instance().Now();
+}
+
+} // namespace fml
diff --git a/fml/time/dart_timestamp_provider.h b/fml/time/dart_timestamp_provider.h
new file mode 100644
index 0000000..97ab6b1
--- /dev/null
+++ b/fml/time/dart_timestamp_provider.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Flutter 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_DART_TIMESTAMP_PROVIDER_H_
+#define FLUTTER_FML_TIME_DART_TIMESTAMP_PROVIDER_H_
+
+#include "flutter/fml/time/timestamp_provider.h"
+
+#include "flutter/fml/macros.h"
+#include "flutter/fml/time/time_point.h"
+
+namespace fml {
+
+fml::TimePoint DartTimelineTicksSinceEpoch();
+
+/// TimestampProvider implementation that is backed by Dart_TimelineGetTicks
+class DartTimestampProvider : TimestampProvider {
+ public:
+ static DartTimestampProvider& Instance() {
+ static DartTimestampProvider instance;
+ return instance;
+ }
+
+ ~DartTimestampProvider() override;
+
+ fml::TimePoint Now() override;
+
+ private:
+ static constexpr int64_t kNanosPerSecond = 1000000000;
+
+ int64_t ConvertToNanos(int64_t ticks, int64_t frequency);
+
+ DartTimestampProvider();
+
+ FML_DISALLOW_COPY_AND_ASSIGN(DartTimestampProvider);
+};
+
+} // namespace fml
+
+#endif // FLUTTER_FML_TIME_DART_TIMESTAMP_PROVIDER_H_
diff --git a/fml/time/time_point.cc b/fml/time/time_point.cc
index 7c54d70..e3bd652 100644
--- a/fml/time/time_point.cc
+++ b/fml/time/time_point.cc
@@ -6,6 +6,7 @@
#include "flutter/fml/build_config.h"
#include "flutter/fml/logging.h"
+#include "flutter/fml/time/dart_timestamp_provider.h"
#if defined(OS_FUCHSIA)
#include <zircon/syscalls.h>
@@ -36,8 +37,7 @@
}
TimePoint TimePoint::Now() {
- const int64_t nanos = NanosSinceEpoch(std::chrono::steady_clock::now());
- return TimePoint(nanos);
+ return DartTimelineTicksSinceEpoch();
}
TimePoint TimePoint::CurrentWallTime() {
diff --git a/fml/time/time_point.h b/fml/time/time_point.h
index 456bc5c..1960234 100644
--- a/fml/time/time_point.h
+++ b/fml/time/time_point.h
@@ -39,6 +39,7 @@
return TimePoint(ticks.ToNanoseconds());
}
+ // Expects ticks in nanos.
static constexpr TimePoint FromTicks(int64_t ticks) {
return TimePoint(ticks);
}
diff --git a/fml/time/time_point_unittest.cc b/fml/time/time_point_unittest.cc
index 9b4ca76..32b35ed 100644
--- a/fml/time/time_point_unittest.cc
+++ b/fml/time/time_point_unittest.cc
@@ -4,6 +4,10 @@
#include "flutter/fml/time/chrono_timestamp_provider.h"
+#include "flutter/fml/time/dart_timestamp_provider.h"
+
+#include <thread>
+
#include "gtest/gtest.h"
namespace fml {
@@ -14,5 +18,18 @@
EXPECT_GT(TimePoint::Max(), ChronoTicksSinceEpoch());
}
+TEST(TimePoint, DartClockIsMonotonic) {
+ using namespace std::chrono_literals;
+ const auto t1 = DartTimelineTicksSinceEpoch();
+ std::this_thread::sleep_for(1us);
+ const auto t2 = DartTimelineTicksSinceEpoch();
+ std::this_thread::sleep_for(1us);
+ const auto t3 = DartTimelineTicksSinceEpoch();
+ EXPECT_LT(TimePoint::Min(), t1);
+ EXPECT_LE(t1, t2);
+ EXPECT_LE(t2, t3);
+ EXPECT_LT(t3, TimePoint::Max());
+}
+
} // namespace
} // namespace fml