summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-09-16 00:44:33 +0200
committerKonstantin Käfer <mail@kkaefer.com>2017-09-16 01:35:44 +0200
commite79c8db871d4631fb480c679309c827c7ccd2e56 (patch)
tree964d8b0d3687a829a252fac20482fdd3030c0430
parent0b8bc22483c61175012d3348ac724142cbac9c7d (diff)
downloadqtlocation-mapboxgl-upstream/expired-resources.tar.gz
[core] make sure tiles are not treated as complete until all worker operations completedupstream/expired-resources
Previously, when we started a worker operation that eventually throws an exception (e.g. due to the tile not being parseable), and then enqueue another worker operation while the first one is processing, we treated the worker as idle once the first operation's error callback fired, even though the second operation was still in progress. Due to our use of coalescing, I was unable to come up with a reliable test since we'd need to reproduce the behavior described above, which is timing dependent.
-rw-r--r--src/mbgl/tile/geometry_tile.cpp13
-rw-r--r--src/mbgl/tile/geometry_tile.hpp20
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp16
-rw-r--r--src/mbgl/tile/raster_tile.cpp15
-rw-r--r--src/mbgl/tile/raster_tile.hpp6
-rw-r--r--src/mbgl/tile/raster_tile_worker.cpp8
-rw-r--r--src/mbgl/tile/raster_tile_worker.hpp2
-rw-r--r--test/tile/annotation_tile.test.cpp9
-rw-r--r--test/tile/geojson_tile.test.cpp5
-rw-r--r--test/tile/raster_tile.test.cpp6
-rw-r--r--test/tile/vector_tile.test.cpp9
11 files changed, 56 insertions, 53 deletions
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index fafd9f7ae7..c99149893d 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -140,9 +140,10 @@ void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers)
worker.invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID);
}
-void GeometryTile::onLayout(LayoutResult result) {
+void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelationID) {
loaded = true;
renderable = true;
+ (void)resultCorrelationID;
nonSymbolBuckets = std::move(result.nonSymbolBuckets);
featureIndex = std::move(result.featureIndex);
data = std::move(result.tileData);
@@ -150,10 +151,10 @@ void GeometryTile::onLayout(LayoutResult result) {
observer->onTileChanged(*this);
}
-void GeometryTile::onPlacement(PlacementResult result) {
+void GeometryTile::onPlacement(PlacementResult result, const uint64_t resultCorrelationID) {
loaded = true;
renderable = true;
- if (result.correlationID == correlationID) {
+ if (resultCorrelationID == correlationID) {
pending = false;
}
symbolBuckets = std::move(result.symbolBuckets);
@@ -170,9 +171,11 @@ void GeometryTile::onPlacement(PlacementResult result) {
observer->onTileChanged(*this);
}
-void GeometryTile::onError(std::exception_ptr err) {
+void GeometryTile::onError(std::exception_ptr err, const uint64_t resultCorrelationID) {
loaded = true;
- pending = false;
+ if (resultCorrelationID == correlationID) {
+ pending = false;
+ }
observer->onTileError(*this, err);
}
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index ebad0f5410..82c39f782e 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -69,18 +69,15 @@ public:
std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets;
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<GeometryTileData> tileData;
- uint64_t correlationID;
LayoutResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets_,
std::unique_ptr<FeatureIndex> featureIndex_,
- std::unique_ptr<GeometryTileData> tileData_,
- uint64_t correlationID_)
+ std::unique_ptr<GeometryTileData> tileData_)
: nonSymbolBuckets(std::move(nonSymbolBuckets_)),
featureIndex(std::move(featureIndex_)),
- tileData(std::move(tileData_)),
- correlationID(correlationID_) {}
+ tileData(std::move(tileData_)) {}
};
- void onLayout(LayoutResult);
+ void onLayout(LayoutResult, uint64_t correlationID);
class PlacementResult {
public:
@@ -88,22 +85,19 @@ public:
std::unique_ptr<CollisionTile> collisionTile;
optional<AlphaImage> glyphAtlasImage;
optional<PremultipliedImage> iconAtlasImage;
- uint64_t correlationID;
PlacementResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets_,
std::unique_ptr<CollisionTile> collisionTile_,
optional<AlphaImage> glyphAtlasImage_,
- optional<PremultipliedImage> iconAtlasImage_,
- uint64_t correlationID_)
+ optional<PremultipliedImage> iconAtlasImage_)
: symbolBuckets(std::move(symbolBuckets_)),
collisionTile(std::move(collisionTile_)),
glyphAtlasImage(std::move(glyphAtlasImage_)),
- iconAtlasImage(std::move(iconAtlasImage_)),
- correlationID(correlationID_) {}
+ iconAtlasImage(std::move(iconAtlasImage_)) {}
};
- void onPlacement(PlacementResult);
+ void onPlacement(PlacementResult, uint64_t correlationID);
- void onError(std::exception_ptr);
+ void onError(std::exception_ptr, uint64_t correlationID);
float yStretch() const override;
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 4af35e2326..50429420c3 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -88,7 +88,7 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
break;
}
} catch (...) {
- parent.invoke(&GeometryTile::onError, std::current_exception());
+ parent.invoke(&GeometryTile::onError, std::current_exception(), correlationID);
}
}
@@ -112,7 +112,7 @@ void GeometryTileWorker::setLayers(std::vector<Immutable<Layer::Impl>> layers_,
break;
}
} catch (...) {
- parent.invoke(&GeometryTile::onError, std::current_exception());
+ parent.invoke(&GeometryTile::onError, std::current_exception(), correlationID);
}
}
@@ -136,7 +136,7 @@ void GeometryTileWorker::setPlacementConfig(PlacementConfig placementConfig_, ui
break;
}
} catch (...) {
- parent.invoke(&GeometryTile::onError, std::current_exception());
+ parent.invoke(&GeometryTile::onError, std::current_exception(), correlationID);
}
}
@@ -161,7 +161,7 @@ void GeometryTileWorker::symbolDependenciesChanged() {
break;
}
} catch (...) {
- parent.invoke(&GeometryTile::onError, std::current_exception());
+ parent.invoke(&GeometryTile::onError, std::current_exception(), correlationID);
}
}
@@ -187,7 +187,7 @@ void GeometryTileWorker::coalesced() {
break;
}
} catch (...) {
- parent.invoke(&GeometryTile::onError, std::current_exception());
+ parent.invoke(&GeometryTile::onError, std::current_exception(), correlationID);
}
}
@@ -357,8 +357,7 @@ void GeometryTileWorker::redoLayout() {
std::move(buckets),
std::move(featureIndex),
*data ? (*data)->clone() : nullptr,
- correlationID
- });
+ }, correlationID);
attemptPlacement();
}
@@ -422,8 +421,7 @@ void GeometryTileWorker::attemptPlacement() {
std::move(collisionTile),
std::move(glyphAtlasImage),
std::move(iconAtlasImage),
- correlationID
- });
+ }, correlationID);
}
} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
index 76c74ab964..2a3c9eeb0e 100644
--- a/src/mbgl/tile/raster_tile.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -37,18 +37,27 @@ void RasterTile::setData(std::shared_ptr<const std::string> data,
optional<Timestamp> expires_) {
modified = modified_;
expires = expires_;
- worker.invoke(&RasterTileWorker::parse, data);
+
+ pending = true;
+ ++correlationID;
+ worker.invoke(&RasterTileWorker::parse, data, correlationID);
}
-void RasterTile::onParsed(std::unique_ptr<RasterBucket> result) {
+void RasterTile::onParsed(std::unique_ptr<RasterBucket> result, const uint64_t resultCorrelationID) {
bucket = std::move(result);
loaded = true;
+ if (resultCorrelationID == correlationID) {
+ pending = false;
+ }
renderable = bucket ? true : false;
observer->onTileChanged(*this);
}
-void RasterTile::onError(std::exception_ptr err) {
+void RasterTile::onError(std::exception_ptr err, const uint64_t resultCorrelationID) {
loaded = true;
+ if (resultCorrelationID == correlationID) {
+ pending = false;
+ }
observer->onTileError(*this, err);
}
diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp
index 28a27b2b37..2cb64e8ed7 100644
--- a/src/mbgl/tile/raster_tile.hpp
+++ b/src/mbgl/tile/raster_tile.hpp
@@ -36,8 +36,8 @@ public:
void setMask(TileMask&&) override;
- void onParsed(std::unique_ptr<RasterBucket> result);
- void onError(std::exception_ptr);
+ void onParsed(std::unique_ptr<RasterBucket> result, uint64_t correlationID);
+ void onError(std::exception_ptr, uint64_t correlationID);
private:
TileLoader<RasterTile> loader;
@@ -45,6 +45,8 @@ private:
std::shared_ptr<Mailbox> mailbox;
Actor<RasterTileWorker> worker;
+ uint64_t correlationID = 0;
+
// Contains the Bucket object for the tile. Buckets are render
// objects and they get added by tile parsing operations.
std::unique_ptr<RasterBucket> bucket;
diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp
index 3c8af97b40..4afa876429 100644
--- a/src/mbgl/tile/raster_tile_worker.cpp
+++ b/src/mbgl/tile/raster_tile_worker.cpp
@@ -10,17 +10,17 @@ RasterTileWorker::RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTi
: parent(std::move(parent_)) {
}
-void RasterTileWorker::parse(std::shared_ptr<const std::string> data) {
+void RasterTileWorker::parse(std::shared_ptr<const std::string> data, uint64_t correlationID) {
if (!data) {
- parent.invoke(&RasterTile::onParsed, nullptr); // No data; empty tile.
+ parent.invoke(&RasterTile::onParsed, nullptr, correlationID); // No data; empty tile.
return;
}
try {
auto bucket = std::make_unique<RasterBucket>(decodeImage(*data));
- parent.invoke(&RasterTile::onParsed, std::move(bucket));
+ parent.invoke(&RasterTile::onParsed, std::move(bucket), correlationID);
} catch (...) {
- parent.invoke(&RasterTile::onError, std::current_exception());
+ parent.invoke(&RasterTile::onError, std::current_exception(), correlationID);
}
}
diff --git a/src/mbgl/tile/raster_tile_worker.hpp b/src/mbgl/tile/raster_tile_worker.hpp
index 44bc37ca5d..520973c3c3 100644
--- a/src/mbgl/tile/raster_tile_worker.hpp
+++ b/src/mbgl/tile/raster_tile_worker.hpp
@@ -13,7 +13,7 @@ class RasterTileWorker {
public:
RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTile>);
- void parse(std::shared_ptr<const std::string> data);
+ void parse(std::shared_ptr<const std::string> data, uint64_t correlationID);
private:
ActorRef<RasterTile> parent;
diff --git a/test/tile/annotation_tile.test.cpp b/test/tile/annotation_tile.test.cpp
index 86ede07089..8f3f903925 100644
--- a/test/tile/annotation_tile.test.cpp
+++ b/test/tile/annotation_tile.test.cpp
@@ -60,8 +60,7 @@ TEST(AnnotationTile, Issue8289) {
std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
std::make_unique<FeatureIndex>(),
std::move(data),
- 0
- });
+ }, 0);
auto collisionTile = std::make_unique<CollisionTile>(PlacementConfig());
@@ -75,16 +74,14 @@ TEST(AnnotationTile, Issue8289) {
std::move(collisionTile),
{},
{},
- 0
- });
+ }, 0);
// Simulate a second layout with empty data.
tile.onLayout(GeometryTile::LayoutResult {
std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
std::make_unique<FeatureIndex>(),
std::make_unique<AnnotationTileData>(),
- 0
- });
+ }, 0);
std::unordered_map<std::string, std::vector<Feature>> result;
GeometryCoordinates queryGeometry {{ Point<int16_t>(0, 0) }};
diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp
index bb2da1ec62..953c3b8a5f 100644
--- a/test/tile/geojson_tile.test.cpp
+++ b/test/tile/geojson_tile.test.cpp
@@ -109,8 +109,9 @@ TEST(GeoJSONTile, Issue9927) {
ASSERT_NE(nullptr, tile.getBucket(*layer.baseImpl));
// Then simulate a parsing failure and make sure that we keep it renderable in this situation
- // as well.
- tile.onError(std::make_exception_ptr(std::runtime_error("Parse error")));
+ // as well. We're using 3 as a correlationID since we've done two three calls that increment
+ // this counter (as part of the GeoJSONTile constructor, setLayers, and setPlacementConfig).
+ tile.onError(std::make_exception_ptr(std::runtime_error("Parse error")), 3);
ASSERT_TRUE(tile.isRenderable());
ASSERT_NE(nullptr, tile.getBucket(*layer.baseImpl));
}
diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp
index efdc4767d9..8b2b3dee61 100644
--- a/test/tile/raster_tile.test.cpp
+++ b/test/tile/raster_tile.test.cpp
@@ -53,7 +53,7 @@ TEST(RasterTile, setError) {
TEST(RasterTile, onError) {
RasterTileTest test;
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
- tile.onError(std::make_exception_ptr(std::runtime_error("test")));
+ tile.onError(std::make_exception_ptr(std::runtime_error("test")), 0);
EXPECT_FALSE(tile.isRenderable());
EXPECT_TRUE(tile.isLoaded());
EXPECT_TRUE(tile.isComplete());
@@ -62,7 +62,7 @@ TEST(RasterTile, onError) {
TEST(RasterTile, onParsed) {
RasterTileTest test;
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
- tile.onParsed(std::make_unique<RasterBucket>(PremultipliedImage{}));
+ tile.onParsed(std::make_unique<RasterBucket>(PremultipliedImage{}), 0);
EXPECT_TRUE(tile.isRenderable());
EXPECT_TRUE(tile.isLoaded());
EXPECT_TRUE(tile.isComplete());
@@ -85,7 +85,7 @@ TEST(RasterTile, onParsed) {
TEST(RasterTile, onParsedEmpty) {
RasterTileTest test;
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
- tile.onParsed(nullptr);
+ tile.onParsed(nullptr, 0);
EXPECT_FALSE(tile.isRenderable());
EXPECT_TRUE(tile.isLoaded());
EXPECT_TRUE(tile.isComplete());
diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp
index 45eab21576..7e8b659b7a 100644
--- a/test/tile/vector_tile.test.cpp
+++ b/test/tile/vector_tile.test.cpp
@@ -59,7 +59,8 @@ TEST(VectorTile, setError) {
TEST(VectorTile, onError) {
VectorTileTest test;
VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset);
- tile.onError(std::make_exception_ptr(std::runtime_error("test")));
+ tile.onError(std::make_exception_ptr(std::runtime_error("test")), 0);
+
EXPECT_FALSE(tile.isRenderable());
EXPECT_TRUE(tile.isLoaded());
EXPECT_TRUE(tile.isComplete());
@@ -86,16 +87,14 @@ TEST(VectorTile, Issue7615) {
nullptr,
{},
{},
- 0
- });
+ }, 0);
// Subsequent onLayout should not cause the existing symbol bucket to be discarded.
tile.onLayout(GeometryTile::LayoutResult {
std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
nullptr,
nullptr,
- 0
- });
+ }, 0);
EXPECT_EQ(symbolBucket.get(), tile.getBucket(*symbolLayer.baseImpl));
}