summaryrefslogtreecommitdiff
path: root/src/mbgl/tile/tile_loader_impl.hpp
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-06-13 13:00:20 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-06-13 14:23:54 -0700
commit040bdb1994106516a27edfef8c83c8d6aea3ec87 (patch)
tree70ed47755d542f9ee729bf3a7fa756df6008ece6 /src/mbgl/tile/tile_loader_impl.hpp
parent9a43768667833d23df09782bdb6a2ca582c97b82 (diff)
downloadqtlocation-mapboxgl-040bdb1994106516a27edfef8c83c8d6aea3ec87.tar.gz
[core] TileSource ⇢ TileLoader
Diffstat (limited to 'src/mbgl/tile/tile_loader_impl.hpp')
-rw-r--r--src/mbgl/tile/tile_loader_impl.hpp110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp
new file mode 100644
index 0000000000..2e57f2f6f3
--- /dev/null
+++ b/src/mbgl/tile/tile_loader_impl.hpp
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <mbgl/tile/tile_loader.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/util/tileset.hpp>
+
+#include <cassert>
+
+namespace mbgl {
+
+template <typename T>
+TileLoader<T>::TileLoader(T& tile_,
+ const OverscaledTileID& id,
+ const style::UpdateParameters& parameters,
+ const Tileset& tileset)
+ : tile(tile_),
+ necessity(Necessity::Optional),
+ resource(Resource::tile(
+ tileset.tiles.at(0),
+ parameters.pixelRatio,
+ id.canonical.x,
+ id.canonical.y,
+ id.canonical.z)),
+ fileSource(parameters.fileSource) {
+ assert(!request);
+ if (fileSource.supportsOptionalRequests()) {
+ // When supported, the first request is always optional, even if the TileLoader
+ // is marked as required. That way, we can let the first optional request continue
+ // to load when the TileLoader is later changed from required to optional. If we
+ // started out with a required request, we'd have to cancel everything, including the
+ // initial optional part of the request.
+ loadOptional();
+ } else {
+ // When the FileSource doesn't support optional requests, we do nothing until the
+ // data is definitely required.
+ if (necessity == Necessity::Required) {
+ loadRequired();
+ } else {
+ // We're using this field to check whether the pending request is optional or required.
+ resource.necessity = Resource::Optional;
+ }
+ }
+}
+
+template <typename T>
+void TileLoader<T>::loadOptional() {
+ assert(!request);
+
+ resource.necessity = Resource::Optional;
+ request = fileSource.request(resource, [this](Response res) {
+ request.reset();
+
+ tile.setTriedOptional();
+
+ if (res.error && res.error->reason == Response::Error::Reason::NotFound) {
+ // When the optional request could not be satisfied, don't treat it as an error.
+ // Instead, we make sure that the next request knows that there has been an optional
+ // request before by setting one of the prior* fields.
+ resource.priorExpires = Timestamp{ Seconds::zero() };
+ } else {
+ loadedData(res);
+ }
+
+ if (necessity == Necessity::Required) {
+ loadRequired();
+ }
+ });
+}
+
+template <typename T>
+void TileLoader<T>::makeRequired() {
+ if (!request) {
+ loadRequired();
+ }
+}
+
+template <typename T>
+void TileLoader<T>::makeOptional() {
+ if (resource.necessity == Resource::Required && request) {
+ // Abort a potential HTTP request.
+ request.reset();
+ }
+}
+
+template <typename T>
+void TileLoader<T>::loadedData(const Response& res) {
+ if (res.error && res.error->reason != Response::Error::Reason::NotFound) {
+ tile.setError(std::make_exception_ptr(std::runtime_error(res.error->message)));
+ } else if (res.notModified) {
+ resource.priorExpires = res.expires;
+ // Do not notify the tile; when we get this message, it already has the current
+ // version of the data.
+ } else {
+ resource.priorModified = res.modified;
+ resource.priorExpires = res.expires;
+ resource.priorEtag = res.etag;
+ tile.setData(res.noContent ? nullptr : res.data, res.modified, res.expires);
+ }
+}
+
+template <typename T>
+void TileLoader<T>::loadRequired() {
+ assert(!request);
+
+ resource.necessity = Resource::Required;
+ request = fileSource.request(resource, [this](Response res) { loadedData(res); });
+}
+
+} // namespace mbgl