From 77b24bc0d3ddfda494cf1a7ce4090ff3a79324e4 Mon Sep 17 00:00:00 2001 From: Chris Loer Date: Wed, 17 May 2017 13:49:48 -0700 Subject: [core] Throttle tiles to redo symbol placement at most once every 300ms. Fixes issue #8435 and prepares for pitch-scaling changes in issue #8967. --- cmake/core-files.cmake | 2 ++ src/mbgl/tile/geometry_tile.cpp | 12 ++++++++++-- src/mbgl/tile/geometry_tile.hpp | 4 ++++ src/mbgl/util/throttler.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/mbgl/util/throttler.hpp | 22 ++++++++++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/mbgl/util/throttler.cpp create mode 100644 src/mbgl/util/throttler.hpp diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 90b8d97afe..dfe11b82b8 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -593,6 +593,8 @@ set(MBGL_CORE_FILES src/mbgl/util/thread_context.cpp src/mbgl/util/thread_context.hpp src/mbgl/util/thread_local.hpp + src/mbgl/util/throttler.cpp + src/mbgl/util/throttler.hpp src/mbgl/util/tile_coordinate.hpp src/mbgl/util/tile_cover.cpp src/mbgl/util/tile_cover.hpp diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 3da429ddf6..8f14a9c8aa 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,8 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_, obsolete, parameters.mode), glyphAtlas(glyphAtlas_), - spriteAtlas(spriteAtlas_) { + spriteAtlas(spriteAtlas_), + placementThrottler(Milliseconds(300), [this] { invokePlacement(); }) { } GeometryTile::~GeometryTile() { @@ -85,7 +87,13 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { ++correlationID; requestedConfig = desiredConfig; - worker.invoke(&GeometryTileWorker::setPlacementConfig, desiredConfig, correlationID); + placementThrottler.invoke(); +} + +void GeometryTile::invokePlacement() { + if (requestedConfig) { + worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID); + } } void GeometryTile::redoLayout() { diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 7d275fc72c..6e4c29d723 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -88,6 +89,7 @@ protected: private: void markObsolete(); + void invokePlacement(); const std::string sourceID; style::Style& style; @@ -110,6 +112,8 @@ private: std::unordered_map> symbolBuckets; std::unique_ptr collisionTile; + + util::Throttler placementThrottler; }; } // namespace mbgl diff --git a/src/mbgl/util/throttler.cpp b/src/mbgl/util/throttler.cpp new file mode 100644 index 0000000000..910810ce2f --- /dev/null +++ b/src/mbgl/util/throttler.cpp @@ -0,0 +1,36 @@ +#include + +namespace mbgl { +namespace util { + +Throttler::Throttler(Duration frequency_, std::function&& function_) + : frequency(frequency_) + , function(std::move(function_)) + , pendingInvocation(false) + , lastInvocation(TimePoint::min()) +{} + +void Throttler::invoke() { + if (pendingInvocation) { + return; + } + + Duration timeToNextInvocation = lastInvocation == TimePoint::min() + ? Duration::zero() + : (lastInvocation + frequency) - Clock::now(); + + if (timeToNextInvocation <= Duration::zero()) { + lastInvocation = Clock::now(); + function(); + } else { + pendingInvocation = true; + timer.start(timeToNextInvocation, Duration::zero(), [this]{ + pendingInvocation = false; + lastInvocation = Clock::now(); + function(); + }); + } +} + +} // namespace util +} // namespace mbgl diff --git a/src/mbgl/util/throttler.hpp b/src/mbgl/util/throttler.hpp new file mode 100644 index 0000000000..175de7ccaf --- /dev/null +++ b/src/mbgl/util/throttler.hpp @@ -0,0 +1,22 @@ +#include +#include + +namespace mbgl { +namespace util { + +class Throttler { +public: + Throttler(Duration frequency, std::function&& function); + + void invoke(); +private: + Duration frequency; + std::function function; + + Timer timer; + bool pendingInvocation; + TimePoint lastInvocation; +}; + +} // namespace util +} // namespace mbgl -- cgit v1.2.1