From 24dff5b4f4ae781dd4ab1b814cc0b2a46b158d80 Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Mon, 25 Sep 2017 11:38:04 -0700 Subject: actor ref-actor --- .../mbgl/style/sources/custom_vector_source.hpp | 29 ++++++-- .../sources/render_custom_vector_source.cpp | 43 ++---------- .../sources/render_custom_vector_source.hpp | 5 +- src/mbgl/style/sources/custom_vector_source.cpp | 80 +++++++++++++++++++++- .../style/sources/custom_vector_source_impl.cpp | 16 +++-- .../style/sources/custom_vector_source_impl.hpp | 10 +-- src/mbgl/tile/custom_tile.cpp | 33 +++++---- src/mbgl/tile/custom_tile.hpp | 15 ++-- 8 files changed, 156 insertions(+), 75 deletions(-) diff --git a/include/mbgl/style/sources/custom_vector_source.hpp b/include/mbgl/style/sources/custom_vector_source.hpp index a256c8e7f7..78835f2bed 100644 --- a/include/mbgl/style/sources/custom_vector_source.hpp +++ b/include/mbgl/style/sources/custom_vector_source.hpp @@ -5,30 +5,47 @@ #include #include #include +#include +#include namespace mbgl { namespace style { struct Error { std::string message; }; -using FetchTileResult = variant< - mapbox::geojson::geojson, - Error>; +using SetTileDataFunction = std::function; +using TileFunction = std::function; -using FetchTileCallback = std::function; -using FetchTileFunction = std::function; +class CustomTileLoader : private util::noncopyable { +public: + CustomTileLoader(TileFunction&& fetchTileFn, TileFunction&& cancelTileFn); + ~CustomTileLoader(); + void fetchTile(const CanonicalTileID& tileID, ActorRef callbackRef); + void cancelTile(const CanonicalTileID& tileID); + void setTileData(const CanonicalTileID& tileID, const mapbox::geojson::geojson& data); + void removeTile(const CanonicalTileID& tileID); +private: + class Impl; + Impl* impl = nullptr; +}; class CustomVectorSource : public Source { public: CustomVectorSource(std::string id, GeoJSONOptions options, - FetchTileFunction fetchTile); + TileFunction fetchTile, + TileFunction cancelTile); void loadDescription(FileSource&) final; + void setTileData(const CanonicalTileID&, const mapbox::geojson::geojson& geojson); // Private implementation class Impl; const Impl& impl() const; +private: + std::shared_ptr mailbox; + CustomTileLoader loader; + }; template <> diff --git a/src/mbgl/renderer/sources/render_custom_vector_source.cpp b/src/mbgl/renderer/sources/render_custom_vector_source.cpp index b6c27bb00c..76cc649834 100644 --- a/src/mbgl/renderer/sources/render_custom_vector_source.cpp +++ b/src/mbgl/renderer/sources/render_custom_vector_source.cpp @@ -1,14 +1,11 @@ #include #include #include -#include -#include +#include #include #include -#include - namespace mbgl { using namespace style; @@ -26,35 +23,6 @@ bool RenderCustomVectorSource::isLoaded() const { return tilePyramid.isLoaded(); } -void RenderCustomVectorSource::setTileData(const CanonicalTileID& tileID, - const style::FetchTileResult& result) { - if (result.is()) { - Log::Error(Event::Render, "FetchTile (%d, %d, %d) error: %s", tileID.z, tileID.x, tileID.y, result.get().message.c_str()); - return; - } - - auto geoJSON = result.get(); - auto data = mapbox::geometry::feature_collection(); - if (geoJSON.is() && !geoJSON.get().empty()) { - const GeoJSONOptions options = impl().getOptions(); - - const double scale = util::EXTENT / options.tileSize; - - mapbox::geojsonvt::Options vtOptions; - vtOptions.maxZoom = options.maxzoom; - vtOptions.extent = util::EXTENT; - vtOptions.buffer = std::round(scale * options.buffer); - vtOptions.tolerance = scale * options.tolerance; - auto geojsonVt = std::make_unique(geoJSON, vtOptions); - data = geojsonVt->getTile(tileID.z, tileID.x, tileID.y).features; - } - for (auto const& item : tilePyramid.tiles) { - if (item.first.canonical == tileID) { - static_cast(item.second.get())->updateData(data); - } - } -} - void RenderCustomVectorSource::update(Immutable baseImpl_, const std::vector>& layers, const bool needsRendering, @@ -64,9 +32,11 @@ void RenderCustomVectorSource::update(Immutable baseImpl_, enabled = needsRendering; - auto fetchTile = impl().getFetchTileFunction(); + auto tileLoader = impl().getTileLoader(); - FetchTileCallback fetchTileCallback = std::bind(&RenderCustomVectorSource::setTileData, this, std::placeholders::_1, std::placeholders::_2); + if (!tileLoader) { + return; + } const GeoJSONOptions options = impl().getOptions(); tilePyramid.update(layers, @@ -77,8 +47,7 @@ void RenderCustomVectorSource::update(Immutable baseImpl_, util::tileSize, { options.minzoom, options.maxzoom }, [&] (const OverscaledTileID& tileID) { - fetchTile(tileID.canonical, fetchTileCallback); - return std::make_unique(tileID, impl().id, parameters, mapbox::geometry::feature_collection()); + return std::make_unique(tileID, impl().id, parameters, impl().getOptions(), *tileLoader); }); } diff --git a/src/mbgl/renderer/sources/render_custom_vector_source.hpp b/src/mbgl/renderer/sources/render_custom_vector_source.hpp index 43e5094cc1..b52fa196d2 100644 --- a/src/mbgl/renderer/sources/render_custom_vector_source.hpp +++ b/src/mbgl/renderer/sources/render_custom_vector_source.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { @@ -34,9 +35,7 @@ public: void onLowMemory() final; void dumpDebugLogs() const final; - - void setTileData(const CanonicalTileID& tileID, const style::FetchTileResult& result); - + private: const style::CustomVectorSource::Impl& impl() const; diff --git a/src/mbgl/style/sources/custom_vector_source.cpp b/src/mbgl/style/sources/custom_vector_source.cpp index e0bbd85af7..38e708a7a8 100644 --- a/src/mbgl/style/sources/custom_vector_source.cpp +++ b/src/mbgl/style/sources/custom_vector_source.cpp @@ -1,18 +1,94 @@ #include #include +#include namespace mbgl { namespace style { +class CustomTileLoader::Impl { +public: + Impl(TileFunction&& fetchTileFn, TileFunction&& cancelTileFn) { + fetchTileFunction = std::move(fetchTileFn); + cancelTileFunction = std::move(cancelTileFn); + } + + void fetchTile(const CanonicalTileID& tileID, ActorRef callbackRef) { + fetchTileFunction(tileID); + auto insertResult = tileCallbackMap.insert({tileID, callbackRef}); + if (insertResult.second == false) { + insertResult.first->second = callbackRef; + } + } + + void cancelTile(const CanonicalTileID& tileID) { + if(tileCallbackMap.find(tileID) != tileCallbackMap.end()) + cancelTileFunction(tileID); + } + + void removeTile(const CanonicalTileID& tileID) { + tileCallbackMap.erase(tileID); + } + + void setTileData(const CanonicalTileID& tileID, const mapbox::geojson::geojson& data) { + auto iter = tileCallbackMap.find(tileID); + if (iter == tileCallbackMap.end()) return; + iter->second.invoke(&SetTileDataFunction::operator(), tileID, data); + } + +private: + TileFunction fetchTileFunction; + TileFunction cancelTileFunction; + std::unordered_map> tileCallbackMap; +}; + + +CustomTileLoader::CustomTileLoader(TileFunction&& fetchTileFn, TileFunction&& cancelTileFn) + : impl(new CustomTileLoader::Impl(std::move(fetchTileFn), std::move(cancelTileFn))) { + +} + +CustomTileLoader::~CustomTileLoader() { + delete impl; + impl = nullptr; +} + +void CustomTileLoader::fetchTile(const CanonicalTileID& tileID, ActorRef callbackRef) { + impl->fetchTile(tileID, callbackRef); +} + +void CustomTileLoader::cancelTile(const CanonicalTileID& tileID) { + impl->cancelTile(tileID); +} + +void CustomTileLoader::setTileData(const CanonicalTileID& tileID, const mapbox::geojson::geojson& data) { + impl->setTileData(tileID, data); +} + +void CustomTileLoader::removeTile(const CanonicalTileID& tileID) { + impl->removeTile(tileID); +} + CustomVectorSource::CustomVectorSource(std::string id, const GeoJSONOptions options, - FetchTileFunction fetchTileFn) - : Source(makeMutable(std::move(id), options, fetchTileFn)) { + TileFunction fetchTileFn, + TileFunction cancelTileFn) + : Source(makeMutable(std::move(id), options)), + mailbox(std::make_shared(*Scheduler::GetCurrent())), + loader(std::move(fetchTileFn), std::move(cancelTileFn)) { } +const CustomVectorSource::Impl& CustomVectorSource::impl() const { + return static_cast(*baseImpl); +} void CustomVectorSource::loadDescription(FileSource&) { + baseImpl = makeMutable(impl(), ActorRef(loader, mailbox)); loaded = true; } +void CustomVectorSource::setTileData(const CanonicalTileID& tileID, + const mapbox::geojson::geojson& data) { + loader.setTileData(tileID, data); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/custom_vector_source_impl.cpp b/src/mbgl/style/sources/custom_vector_source_impl.cpp index 1b5ee4e5d1..d1f20045cb 100644 --- a/src/mbgl/style/sources/custom_vector_source_impl.cpp +++ b/src/mbgl/style/sources/custom_vector_source_impl.cpp @@ -9,11 +9,17 @@ namespace mbgl { namespace style { CustomVectorSource::Impl::Impl(std::string id_, - const GeoJSONOptions options_, - FetchTileFunction fetchTileFn_) + const GeoJSONOptions options_) : Source::Impl(SourceType::CustomVector, std::move(id_)), options(options_), - fetchTileFn(fetchTileFn_) { + loaderRef({}) { +} + +CustomVectorSource::Impl::Impl(const Impl& impl, ActorRef loaderRef_) + : Source::Impl(impl), + options(impl.options), + loaderRef(loaderRef_){ + } optional CustomVectorSource::Impl::getAttribution() const { @@ -24,8 +30,8 @@ GeoJSONOptions CustomVectorSource::Impl::getOptions() const { return options; } -FetchTileFunction CustomVectorSource::Impl::getFetchTileFunction() const { - return fetchTileFn; +optional> CustomVectorSource::Impl::getTileLoader() const { + return loaderRef; } } // namespace style diff --git a/src/mbgl/style/sources/custom_vector_source_impl.hpp b/src/mbgl/style/sources/custom_vector_source_impl.hpp index aa07bc800d..af103f4c7e 100644 --- a/src/mbgl/style/sources/custom_vector_source_impl.hpp +++ b/src/mbgl/style/sources/custom_vector_source_impl.hpp @@ -3,24 +3,24 @@ #include #include #include +#include namespace mbgl { namespace style { class CustomVectorSource::Impl : public Source::Impl { public: - Impl(std::string id, - GeoJSONOptions options, - FetchTileFunction fetchTileFn); + Impl(std::string id, GeoJSONOptions options); + Impl(const Impl&, ActorRef); optional getAttribution() const final; GeoJSONOptions getOptions() const; - FetchTileFunction getFetchTileFunction() const; + optional> getTileLoader() const; private: GeoJSONOptions options; - FetchTileFunction fetchTileFn; + optional> loaderRef; }; } // namespace style diff --git a/src/mbgl/tile/custom_tile.cpp b/src/mbgl/tile/custom_tile.cpp index b7057d447e..c462e95d0f 100644 --- a/src/mbgl/tile/custom_tile.cpp +++ b/src/mbgl/tile/custom_tile.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,24 +10,26 @@ #include namespace mbgl { +namespace style { CustomTile::CustomTile(const OverscaledTileID& overscaledTileID, std::string sourceID_, const TileParameters& parameters, - const style::GeoJSONOptions options_) + const style::GeoJSONOptions options_, + ActorRef loader_) : GeometryTile(overscaledTileID, sourceID_, parameters), + necessity(Resource::Optional), options(options_), + loader(loader_), actor(*Scheduler::GetCurrent(), std::bind(&CustomTile::setTileData, this, std::placeholders::_1, std::placeholders::_2)) { +} +CustomTile::~CustomTile() { + loader.invoke(&style::CustomTileLoader::removeTile, id.canonical); } -void CustomTile::setTileData(const CanonicalTileID&, const style::FetchTileResult& result) { - if (result.is()) { - Log::Error(Event::Render, "FetchTile (%d, %d, %d) error: %s", id.canonical.z, id.canonical.x, id.canonical.y, result.get().message.c_str()); - return; - } +void CustomTile::setTileData(const CanonicalTileID&, const mapbox::geojson::geojson& geoJSON) { - auto geoJSON = result.get(); auto data = mapbox::geometry::feature_collection(); if (geoJSON.is() && !geoJSON.get().empty()) { const double scale = util::EXTENT / options.tileSize; @@ -42,7 +45,16 @@ void CustomTile::setTileData(const CanonicalTileID&, const style::FetchTileResul setData(std::make_unique(std::move(data))); } -void CustomTile::setNecessity(Necessity) {} +void CustomTile::setNecessity(Necessity newNecessity) { + if (newNecessity != necessity) { + necessity = newNecessity; + if (necessity == Necessity::Required) { + loader.invoke(&style::CustomTileLoader::fetchTile, id.canonical, actor.self()); + } else if(!isRenderable()) { + loader.invoke(&style::CustomTileLoader::cancelTile, id.canonical); + } + } +} void CustomTile::querySourceFeatures( std::vector& result, @@ -66,8 +78,5 @@ void CustomTile::querySourceFeatures( } } -ActorRef CustomTile::fetchTileCallback() { - return actor.self(); -} - +} // namespace style } // namespace mbgl diff --git a/src/mbgl/tile/custom_tile.hpp b/src/mbgl/tile/custom_tile.hpp index 66606d2224..734ea2bac1 100644 --- a/src/mbgl/tile/custom_tile.hpp +++ b/src/mbgl/tile/custom_tile.hpp @@ -9,14 +9,17 @@ namespace mbgl { class TileParameters; +namespace style { + class CustomTile: public GeometryTile { public: CustomTile(const OverscaledTileID&, std::string sourceID, const TileParameters&, - const style::GeoJSONOptions); - - void setTileData(const CanonicalTileID& tileID, const style::FetchTileResult& result); + const style::GeoJSONOptions, + ActorRef loader); + ~CustomTile() override; + void setTileData(const CanonicalTileID& tileID, const mapbox::geojson::geojson& data); void setNecessity(Necessity) final; @@ -24,10 +27,12 @@ public: std::vector& result, const SourceQueryOptions&) override; - ActorRef fetchTileCallback(); private: + Necessity necessity; const style::GeoJSONOptions options; - Actor actor; + ActorRef loader; + Actor actor; }; +} // namespace style } // namespace mbgl -- cgit v1.2.1