Otherwise, this will remove them from the map and overwrite the old data. This could happen e.g. when we have connection trouble and a tile needs to be refreshed, or we're displaying stale information and the connection is down.
Previously, the placement of symbols depended on the order in which the
glyphs they need were loaded. The placement order should be based on the
style.
To fix this, symbol layers are placed in `placementPending` after they
are parsed. After all layers are parsed, symbol layers (stored in
`placementPending`) are placed and returned.
* Standardize on std::exception_ptr as the error representation
(fixes#2854).
* Don't format textual strings at the error source; pass on the
constituent data via observer method parameters instead.
* Use the null object pattern to simplify observer notification code.
* Further refactoring for ResourceLoading tests.
This fixes adding shape annotations after VectorTileData objects have
been created for annotations already, and will also be necessary for
the dynamic Style API.
To encapsulate the differences, this introduces an abstract
GeometryTileMonitor class, with concrete VectorTileMonitor and
AnnotationTileMonitor implementations, and makes pbf parsing for
VectorTile data happen lazily in getLayer, since we want that to
happen on the worker thread, rather than when VectorTile is created.
Fixes#2792
We're now reparsing tiles when they expire. We're also swapping out buckets atomically to avoid flickering data; i.e. we're displaying the old data as long as we don't have a new parsed bucket for that layer yet. The parsed buckets now live in the *TileData objects rather than in the TileWorker; only partially parsed == pending buckets will remain in the TileWorker. Once they're parsed, they're moved to the *TileData object.
We're now returning stale responses from cache. Those responses will have the `stale` flag set to true. Currently, all requesters in the core code discard stale responses, and cancel the request immediately after they got a non-stale response.
By not automatically destroying Request objects after the result has been delivered, we are making sure that we can potentially fire the callback multiple times without adverse effects. This means that you have to hold on to the result of fs->request(), can explicitly cancel it if you don't want to be notified of data changes anymore. Not doing so will monitor the request indefinitely and will prevent the app from exiting.
This condition led to layers with high minzoom like oneway street
arrows (z15) get parsed and placed regardless of minzoom (e.g. z11+),
wasting a lot of worker CPU time.
It became unnecessary after we added reparsing tiles when overscaling,
and even before that it should have probably been <= rather than <.
This is needed because of a race that can occur now that we
requests Glyphs from the Map Thread:
The glyph might arrive at the moment a tile is being parsed
and they won't be notified again of any new data, remaining
forever at the partial state.
Layers are added and removed dynamically on the Map thread when we use shape
annotations and we are iterating style.layers on the Worker thread without
any lock.
Now when we create a [Live|Vector]TileData at the Map thread we give it
a layers list (instead of the Style) and [Live|Vector]TileData will ultimately
make a copy of this list (on the Map thread, so no concurrency with
adding shape annotations).
The copy should be relatively cheap because we are using a shared pointer
for storing the layers on the list.
After parsing a tile, it redoes placement for that tile if the angle has
changed since it started parsing. These redo calls were accidentally
done from the worker thread. Assigning the new work to `workRequest`
caused it to cancel itself.
Fix the problem by calling redoPlacement from the map thread.
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.