From 148cfe9e554e065a2a6e56f0ce4e7d19971e6902 Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Tue, 9 Jul 2019 19:03:17 +0300 Subject: [PATCH] [core] Decouple style change and transitions update Update transitions in a separate call chain in order to avoid infinite loop, in case map is modified from within the transitions update callback. --- src/mbgl/map/map_impl.cpp | 33 ++++++++++++++++++++------------- src/mbgl/map/map_impl.hpp | 6 ++++++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp index 69c3de97834..fd4a1e6f83b 100644 --- a/src/mbgl/map/map_impl.cpp +++ b/src/mbgl/map/map_impl.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -11,15 +12,17 @@ Map::Impl::Impl(RendererFrontend& frontend_, MapObserver& observer_, std::shared_ptr fileSource_, const MapOptions& mapOptions) - : observer(observer_), - rendererFrontend(frontend_), - transform(observer, mapOptions.constrainMode(), mapOptions.viewportMode()), - mode(mapOptions.mapMode()), - pixelRatio(mapOptions.pixelRatio()), - crossSourceCollisions(mapOptions.crossSourceCollisions()), - fileSource(std::move(fileSource_)), - style(std::make_unique(*fileSource, pixelRatio)), - annotationManager(*style) { + : observer(observer_), + rendererFrontend(frontend_), + transform(observer, mapOptions.constrainMode(), mapOptions.viewportMode()), + mode(mapOptions.mapMode()), + pixelRatio(mapOptions.pixelRatio()), + crossSourceCollisions(mapOptions.crossSourceCollisions()), + fileSource(std::move(fileSource_)), + style(std::make_unique(*fileSource, pixelRatio)), + annotationManager(*style), + mailbox(std::make_shared(*Scheduler::GetCurrent())), + actor(*this, mailbox) { transform.setNorthOrientation(mapOptions.northOrientation()); style->impl->setObserver(this); rendererFrontend.setObserver(*this); @@ -39,12 +42,16 @@ void Map::Impl::onSourceChanged(style::Source& source) { } void Map::Impl::onUpdate() { - // Don't load/render anything in still mode until explicitly requested. - if (mode != MapMode::Continuous && !stillImageRequest) { - return; + if (mode == MapMode::Continuous) { + actor.invoke(&Map::Impl::updateInternal, Clock::now()); + } else if (stillImageRequest) { + updateInternal(Clock::time_point::max()); } +} - TimePoint timePoint = mode == MapMode::Continuous ? Clock::now() : Clock::time_point::max(); +void Map::Impl::updateInternal(TimePoint timePoint) { + // Don't load/render anything in still mode until explicitly requested. + assert(mode == MapMode::Continuous || stillImageRequest); transform.updateTransitions(timePoint); diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp index 416662f9e56..aaa9a1d7cdc 100644 --- a/src/mbgl/map/map_impl.hpp +++ b/src/mbgl/map/map_impl.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -51,6 +52,9 @@ class Map::Impl : public style::Observer, public RendererObserver { // Map void jumpTo(const CameraOptions&); + // Internal + void updateInternal(TimePoint timePoint); + MapObserver& observer; RendererFrontend& rendererFrontend; @@ -74,6 +78,8 @@ class Map::Impl : public style::Observer, public RendererObserver { bool loading = false; bool rendererFullyLoaded; std::unique_ptr stillImageRequest; + std::shared_ptr mailbox; + ActorRef actor; }; } // namespace mbgl