summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <thiago@mapbox.com>2015-05-27 18:34:06 +0300
committerThiago Marcos P. Santos <thiago@mapbox.com>2015-05-28 09:33:08 +0300
commitf8cc50683ad52cff702fb3b324502c5e792917a0 (patch)
treeedd32efdce794fc7ece9dc9584452456daa5304e /src
parent48875d8d6ccabd344d95be15f8537b0c8c8f7f18 (diff)
downloadqtlocation-mapboxgl-f8cc50683ad52cff702fb3b324502c5e792917a0.tar.gz
Notify tile parsing errors
The tile parsing is done in a worker thread and if it fails, we set the tile state to "obsolete" and set an error message. When the completion callback is fired, we check for the error message and if it is set, we emit the error signal. The trick here is the signal cannot be emitted directly from the worker thread because that would violate data ownership rules.
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/map/source.cpp30
-rw-r--r--src/mbgl/map/source.hpp2
-rw-r--r--src/mbgl/map/tile_data.cpp15
-rw-r--r--src/mbgl/map/tile_data.hpp16
-rw-r--r--src/mbgl/map/vector_tile_data.cpp6
5 files changed, 50 insertions, 19 deletions
diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp
index eb273d785d..faae3285fe 100644
--- a/src/mbgl/map/source.cpp
+++ b/src/mbgl/map/source.cpp
@@ -287,26 +287,25 @@ TileData::State Source::addTile(MapData& data,
new_tile.data = cache.get(normalized_id.to_uint64());
}
- auto successCallback = std::bind(&Source::emitTileLoaded, this, true);
- auto failureCallback = std::bind(&Source::emitTileLoadingFailed, this, std::placeholders::_1);
-
if (!new_tile.data) {
+ auto callback = std::bind(&Source::tileLoadingCompleteCallback, this, normalized_id);
+
// If we don't find working tile data, we're just going to load it.
if (info.type == SourceType::Vector) {
new_tile.data =
std::make_shared<VectorTileData>(normalized_id, data.transform.getMaxZoom(), style, glyphAtlas,
glyphStore, spriteAtlas, sprite, info);
new_tile.data->request(
- style.workers, transformState.getPixelRatio(), successCallback, failureCallback);
+ style.workers, transformState.getPixelRatio(), callback);
} else if (info.type == SourceType::Raster) {
new_tile.data = std::make_shared<RasterTileData>(normalized_id, texturePool, info);
new_tile.data->request(
- style.workers, transformState.getPixelRatio(), successCallback, failureCallback);
+ style.workers, transformState.getPixelRatio(), callback);
} else if (info.type == SourceType::Annotations) {
new_tile.data = std::make_shared<LiveTileData>(normalized_id, data.annotationManager,
data.transform.getMaxZoom(), style, glyphAtlas,
glyphStore, spriteAtlas, sprite, info);
- new_tile.data->reparse(style.workers, successCallback);
+ new_tile.data->reparse(style.workers, callback);
} else {
throw std::runtime_error("source type not implemented");
}
@@ -539,6 +538,25 @@ void Source::setObserver(Observer* observer) {
observer_ = observer;
}
+void Source::tileLoadingCompleteCallback(const TileID& normalized_id) {
+ auto it = tile_data.find(normalized_id);
+ if (it == tile_data.end()) {
+ return;
+ }
+
+ util::ptr<TileData> data = it->second.lock();
+ if (!data) {
+ return;
+ }
+
+ if (data->getState() == TileData::State::obsolete && !data->getError().empty()) {
+ emitTileLoadingFailed(data->getError());
+ return;
+ }
+
+ emitTileLoaded(true);
+}
+
void Source::emitSourceLoaded() {
if (observer_) {
observer_->onSourceLoaded();
diff --git a/src/mbgl/map/source.hpp b/src/mbgl/map/source.hpp
index d4c29b3e75..174dd996b5 100644
--- a/src/mbgl/map/source.hpp
+++ b/src/mbgl/map/source.hpp
@@ -104,6 +104,8 @@ public:
bool enabled;
private:
+ void tileLoadingCompleteCallback(const TileID& normalized_id);
+
void emitSourceLoaded();
void emitSourceLoadingFailed(const std::string& message);
void emitTileLoaded(bool isNewTile);
diff --git a/src/mbgl/map/tile_data.cpp b/src/mbgl/map/tile_data.cpp
index be0d7d32fe..fc2d48bb5b 100644
--- a/src/mbgl/map/tile_data.cpp
+++ b/src/mbgl/map/tile_data.cpp
@@ -38,18 +38,18 @@ void TileData::setState(const State& state_) {
void TileData::request(Worker& worker,
float pixelRatio,
- const std::function<void()>& successCallback,
- const std::function<void(const std::string& message)>& failureCallback) {
+ const std::function<void()>& callback) {
std::string url = source.tileURL(id, pixelRatio);
state = State::loading;
- req = env.request({ Resource::Kind::Tile, url }, [url, successCallback, failureCallback, &worker, this](const Response &res) {
+ req = env.request({ Resource::Kind::Tile, url }, [url, callback, &worker, this](const Response &res) {
req = nullptr;
if (res.status != Response::Successful) {
std::stringstream message;
message << "Failed to load [" << url << "]: " << res.message;
- failureCallback(message.str());
+ setError(message.str());
+ callback();
return;
}
@@ -57,7 +57,7 @@ void TileData::request(Worker& worker,
data = res.data;
// Schedule tile parsing in another thread
- reparse(worker, successCallback);
+ reparse(worker, callback);
});
}
@@ -88,3 +88,8 @@ bool TileData::reparse(Worker& worker, std::function<void()> callback) {
workRequest = worker.send([this] { parse(); endParsing(); }, callback);
return true;
}
+
+void TileData::setError(const std::string& message) {
+ error = message;
+ setState(State::obsolete);
+}
diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp
index 0d34b2df74..d2a91b880f 100644
--- a/src/mbgl/map/tile_data.hpp
+++ b/src/mbgl/map/tile_data.hpp
@@ -44,10 +44,7 @@ public:
TileData(const TileID&, const SourceInfo&);
~TileData();
- void request(Worker&,
- float pixelRatio,
- const std::function<void()>& successCallback,
- const std::function<void(const std::string& message)>& failureCallback);
+ void request(Worker&, float pixelRatio, const std::function<void()>& callback);
// Schedule a tile reparse on a worker thread and call the callback on
// completion. It will return true if the work was schedule or false it was
@@ -71,13 +68,20 @@ public:
// We let subclasses override setState() so they
// can intercept the state change and react accordingly.
virtual void setState(const State& state);
-
inline State getState() const {
return state;
}
void endParsing();
+ // Error message to be set in case of request
+ // and parsing errors.
+ void setError(const std::string& message);
+
+ std::string getError() const {
+ return error;
+ }
+
// Override this in the child class.
virtual void parse() = 0;
virtual Bucket* getBucket(StyleLayer const &layer_desc) = 0;
@@ -106,6 +110,8 @@ protected:
private:
std::atomic<State> state;
+ std::string error;
+
protected:
// Contains the tile ID string for painting debug information.
DebugFontBuffer debugFontBuffer;
diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp
index 4d77c8ef81..e464c55c90 100644
--- a/src/mbgl/map/vector_tile_data.cpp
+++ b/src/mbgl/map/vector_tile_data.cpp
@@ -59,9 +59,9 @@ void VectorTileData::parse() {
setState(State::parsed);
}
} catch (const std::exception& ex) {
- Log::Error(Event::ParseTile, "Parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what());
- setState(State::obsolete);
- return;
+ std::stringstream message;
+ message << "Failed to parse [" << int(id.z) << "/" << id.x << "/" << id.y << "]: " << ex.what();
+ setError(message.str());
}
}