diff options
-rw-r--r-- | gyp/common.gypi | 1 | ||||
-rw-r--r-- | include/mbgl/ios/MGLMapView.h | 3 | ||||
-rw-r--r-- | include/mbgl/ios/MGLMapboxEvents.h | 1 | ||||
-rw-r--r-- | include/mbgl/map/environment.hpp (renamed from src/mbgl/map/environment.hpp) | 0 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 7 | ||||
-rw-r--r-- | ios/MapboxGL.podspec | 2 | ||||
-rw-r--r-- | ios/app/MBXViewController.mm | 28 | ||||
-rw-r--r-- | macosx/mapboxgl-app.gyp | 1 | ||||
-rw-r--r-- | platform/ios/MGLMapView.mm | 53 | ||||
-rw-r--r-- | platform/ios/MGLMapboxEvents.m | 6 | ||||
-rw-r--r-- | platform/ios/MGLMetricsLocationManager.m | 1 | ||||
-rw-r--r-- | src/mbgl/map/live_tile_data.cpp | 24 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 23 | ||||
-rw-r--r-- | src/mbgl/map/source.cpp | 34 | ||||
-rw-r--r-- | src/mbgl/map/source.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/map/tile_cache.cpp | 60 | ||||
-rw-r--r-- | src/mbgl/map/tile_cache.hpp | 30 | ||||
-rw-r--r-- | src/mbgl/map/tile_data.cpp | 6 | ||||
m--------- | styles | 0 |
19 files changed, 246 insertions, 39 deletions
diff --git a/gyp/common.gypi b/gyp/common.gypi index 01f1451dd0..fbfa687117 100644 --- a/gyp/common.gypi +++ b/gyp/common.gypi @@ -23,6 +23,7 @@ ], 'GCC_WARN_PEDANTIC': 'YES', 'GCC_WARN_UNINITIALIZED_AUTOS': 'YES_AGGRESSIVE', + 'MACOSX_DEPLOYMENT_TARGET': '10.9', }, }, { 'cflags_cc': [ diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h index f2aef61830..8717b5e8a1 100644 --- a/include/mbgl/ios/MGLMapView.h +++ b/include/mbgl/ios/MGLMapView.h @@ -279,6 +279,9 @@ IB_DESIGNABLE /** Toggle the current value of debugActive. */ - (void)toggleDebug; +/** Empties the in-memory tile cache. */ +- (void)emptyMemoryCache; + /** Resets the map to the minimum zoom level, a center coordinate of (0, 0), and a northern heading. */ - (void)resetPosition; diff --git a/include/mbgl/ios/MGLMapboxEvents.h b/include/mbgl/ios/MGLMapboxEvents.h index b10d79e114..b68b9b1b33 100644 --- a/include/mbgl/ios/MGLMapboxEvents.h +++ b/include/mbgl/ios/MGLMapboxEvents.h @@ -11,6 +11,7 @@ extern NSString *const MGLEventKeyZoomLevel; extern NSString *const MGLEventKeySpeed; extern NSString *const MGLEventKeyCourse; extern NSString *const MGLEventKeyAltitude; +extern NSString *const MGLEventKeyHorizontalAccuracy; extern NSString *const MGLEventKeyVerticalAccuracy; extern NSString *const MGLEventKeyPushEnabled; extern NSString *const MGLEventKeyEmailEnabled; diff --git a/src/mbgl/map/environment.hpp b/include/mbgl/map/environment.hpp index 1cd33a5e6d..1cd33a5e6d 100644 --- a/src/mbgl/map/environment.hpp +++ b/include/mbgl/map/environment.hpp diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 38a37a8057..8c7f5f3961 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -152,6 +152,11 @@ public: std::vector<uint32_t> getAnnotationsInBounds(const LatLngBounds&); LatLngBounds getBoundsForAnnotations(const std::vector<uint32_t>&); + // Memory + void setSourceTileCacheSize(size_t); + size_t getSourceTileCacheSize() const { return sourceCacheSize; } + void onLowMemory(); + // Debug void setDebug(bool value); void toggleDebug(); @@ -196,6 +201,8 @@ private: void updateAnnotationTiles(const std::vector<TileID>&); + size_t sourceCacheSize; + enum class Mode : uint8_t { None, // we're not doing any processing Continuous, // continually updating map diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index 2df7062892..b67f7faee7 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.2.10' + m.version = '0.2.13' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' diff --git a/ios/app/MBXViewController.mm b/ios/app/MBXViewController.mm index 509cbbb0e6..13235beb07 100644 --- a/ios/app/MBXViewController.mm +++ b/ios/app/MBXViewController.mm @@ -11,8 +11,8 @@ static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000]; static NSArray *const kStyleNames = @[ - @"Emerald", @"Mapbox Streets", + @"Emerald", @"Light", @"Dark", @"Bright", @@ -21,10 +21,6 @@ static NSArray *const kStyleNames = @[ @"Satellite", ]; -static NSDictionary *const kStyleFileNames = @{ - @"Mapbox Streets": @"mapbox-streets", -}; - static NSString *const kStyleVersion = @"7"; @interface MBXViewController () <UIActionSheetDelegate, MGLMapViewDelegate> @@ -149,6 +145,7 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; otherButtonTitles:@"Reset North", @"Reset Position", @"Toggle Debug", + @"Empty Memory", @"Add 100 Points", @"Add 1,000 Points", @"Add 10,000 Points", @@ -174,18 +171,22 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; } else if (buttonIndex == actionSheet.firstOtherButtonIndex + 3) { - [self parseFeaturesAddingCount:100]; + [self.mapView emptyMemoryCache]; } else if (buttonIndex == actionSheet.firstOtherButtonIndex + 4) { - [self parseFeaturesAddingCount:1000]; + [self parseFeaturesAddingCount:100]; } else if (buttonIndex == actionSheet.firstOtherButtonIndex + 5) { - [self parseFeaturesAddingCount:10000]; + [self parseFeaturesAddingCount:1000]; } else if (buttonIndex == actionSheet.firstOtherButtonIndex + 6) { + [self parseFeaturesAddingCount:10000]; + } + else if (buttonIndex == actionSheet.firstOtherButtonIndex + 7) + { [self.mapView removeAnnotations:self.mapView.annotations]; } } @@ -251,16 +252,11 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; if (index == [kStyleNames count]) index = 0; styleName = [kStyleNames objectAtIndex:index]; } - - NSString *styleFileName = kStyleFileNames[styleName]; - if (!styleFileName) { - styleFileName = [NSString stringWithFormat:@"%@-v%@", - [styleName.lowercaseString stringByReplacingOccurrencesOfString:@" " withString:@"-"], - kStyleVersion]; - } self.mapView.styleURL = [NSURL URLWithString: - [NSString stringWithFormat:@"asset://styles/%@.json", styleFileName]]; + [NSString stringWithFormat:@"asset://styles/%@-v%@.json", + [[styleName lowercaseString] stringByReplacingOccurrencesOfString:@" " withString:@"-"], + kStyleVersion]]; [titleButton setTitle:styleName forState:UIControlStateNormal]; } diff --git a/macosx/mapboxgl-app.gyp b/macosx/mapboxgl-app.gyp index 39aef6435b..9817f9d97c 100644 --- a/macosx/mapboxgl-app.gyp +++ b/macosx/mapboxgl-app.gyp @@ -54,7 +54,6 @@ 'OTHER_LDFLAGS': [ '<@(ldflags)' ], 'SDKROOT': 'macosx', 'INFOPLIST_FILE': 'Info.plist', - 'MACOSX_DEPLOYMENT_TARGET': '10.9', 'CLANG_ENABLE_OBJC_ARC': 'YES' }, } diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 68fae64fac..22a3457aa8 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -45,7 +45,7 @@ const std::string &defaultCacheDatabase() { static dispatch_once_t loadGLExtensions; -NSString *const MGLDefaultStyleName = @"Emerald"; +NSString *const MGLDefaultStyleName = @"mapbox-streets"; NSString *const MGLStyleVersion = @"7"; NSString *const MGLDefaultStyleMarkerSymbolName = @"default_marker"; NSString *const MGLMapboxAccessTokenManagerURLDisplayString = @"mapbox.com/account/apps"; @@ -67,6 +67,8 @@ static NSURL *MGLURLForBundledStyleNamed(NSString *styleName) @property (nonatomic) EAGLContext *context; @property (nonatomic) GLKView *glView; +/** A static view to simulate and obscure `glView` when the app is in the background. */ +@property (nonatomic) UIView *glSnapshotView; @property (nonatomic) NSOperationQueue *regionChangeDelegateQueue; @property (nonatomic) UIImageView *compass; @property (nonatomic) UIImageView *logoBug; @@ -240,6 +242,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [self insertSubview:_glView atIndex:0]; _glView.contentMode = UIViewContentModeCenter; + [self setBackgroundColor:[UIColor clearColor]]; // load extensions @@ -364,6 +367,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; // set initial position // @@ -559,8 +563,31 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; // This is the delegate of the GLKView object's display call. - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - mbglView->resize(rect.size.width, rect.size.height, view.contentScaleFactor, view.drawableWidth, view.drawableHeight); - mbglMap->renderSync(); + if (self.glSnapshotView) + { + NSUInteger snapshotIdx = [self.subviews indexOfObject:self.glSnapshotView]; + NSUInteger glIdx = [self.subviews indexOfObject:self.glView]; + NSAssert(snapshotIdx > glIdx, + @"The snapshot view is the %luth subview, behind the GL view, which is the %luth. " + @"The snapshot view should obscure the GL view to prevent crashing while the app is in the background.", + (unsigned long)snapshotIdx, (unsigned long)glIdx); + } + else + { + mbglView->resize(rect.size.width, rect.size.height, view.contentScaleFactor, view.drawableWidth, view.drawableHeight); + + CGFloat zoomFactor = mbglMap->getMaxZoom() - mbglMap->getMinZoom() + 1; + CGFloat cpuFactor = (CGFloat)[[NSProcessInfo processInfo] processorCount]; + CGFloat memoryFactor = (CGFloat)[[NSProcessInfo processInfo] physicalMemory] / 1000 / 1000 / 1000; + CGFloat sizeFactor = ((CGFloat)mbglMap->getState().getWidth() / mbgl::util::tileSize) * + ((CGFloat)mbglMap->getState().getHeight() / mbgl::util::tileSize); + + NSUInteger cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5; + + mbglMap->setSourceTileCacheSize(cacheSize); + + mbglMap->renderSync(); + } } // This gets called when the view dimension changes, e.g. because the device is being rotated. @@ -583,6 +610,10 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; { [MGLMapboxEvents flush]; + self.glSnapshotView = [self.glView snapshotViewAfterScreenUpdates:YES]; + self.glSnapshotView.autoresizingMask = self.glView.autoresizingMask; + [self insertSubview:self.glSnapshotView aboveSubview:self.glView]; + mbglMap->stop(); [self.glView deleteDrawable]; @@ -593,6 +624,9 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [self.glView bindDrawable]; mbglMap->start(); + + [self.glSnapshotView removeFromSuperview]; + self.glSnapshotView = nil; } - (void)tintColorDidChange @@ -1144,6 +1178,11 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; mbglMap->toggleDebug(); } +- (void)emptyMemoryCache +{ + mbglMap->onLowMemory(); +} + #pragma mark - Geography - + (NSSet *)keyPathsForValuesAffectingCenterCoordinate @@ -2428,7 +2467,8 @@ class MBGLView : public mbgl::View [EAGLContext setCurrentContext:nil]; } - void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight) { + void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight) + { View::resize(width, height, ratio, fbWidth, fbHeight); } @@ -2544,4 +2584,9 @@ class MBGLView : public mbgl::View self.rotateEnabled = allowsRotating; } +- (void)didReceiveMemoryWarning +{ + mbglMap->onLowMemory(); +} + @end diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 90822e6832..605c6a3fa0 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -24,6 +24,7 @@ NSString *const MGLEventKeyZoomLevel = @"zoom"; NSString *const MGLEventKeySpeed = @"speed"; NSString *const MGLEventKeyCourse = @"course"; NSString *const MGLEventKeyAltitude = @"altitude"; +NSString *const MGLEventKeyHorizontalAccuracy = @"horizontalAccuracy"; NSString *const MGLEventKeyVerticalAccuracy = @"verticalAccuracy"; NSString *const MGLEventKeyPushEnabled = @"enabled.push"; NSString *const MGLEventKeyEmailEnabled = @"enabled.email"; @@ -289,14 +290,13 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; // mapbox-events stock attributes [evt setObject:event forKey:@"event"]; [evt setObject:@(1) forKey:@"version"]; - [evt setObject:[weakSelf formatDate:[NSDate date]] forKey:@"created"]; + [evt setObject:[weakSelf.rfc3339DateFormatter stringFromDate:[NSDate date]] forKey:@"created"]; [evt setObject:weakSelf.instanceID forKey:@"instance"]; [evt setObject:weakSelf.advertiserId forKey:@"advertiserId"]; [evt setObject:weakSelf.vendorId forKey:@"vendorId"]; [evt setObject:weakSelf.appBundleId forKeyedSubscript:@"appBundleId"]; // mapbox-events-ios stock attributes - [evt setValue:[weakSelf.rfc3339DateFormatter stringFromDate:[NSDate date]] forKey:@"created"]; [evt setValue:weakSelf.model forKey:@"model"]; [evt setValue:weakSelf.iOSVersion forKey:@"operatingSystem"]; [evt setValue:[weakSelf getDeviceOrientation] forKey:@"orientation"]; @@ -571,7 +571,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; // Can be called from any thread. // - (NSString *) getCurrentCellularNetworkConnectionType { - CTTelephonyNetworkInfo *telephonyInfo = [CTTelephonyNetworkInfo new]; + CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init]; NSString *radioTech = telephonyInfo.currentRadioAccessTechnology; if (radioTech == nil) { diff --git a/platform/ios/MGLMetricsLocationManager.m b/platform/ios/MGLMetricsLocationManager.m index b8b52f38d7..af9b0a71bc 100644 --- a/platform/ios/MGLMetricsLocationManager.m +++ b/platform/ios/MGLMetricsLocationManager.m @@ -47,6 +47,7 @@ MGLEventKeySpeed: @(loc.speed), MGLEventKeyCourse: @(loc.course), MGLEventKeyAltitude: @(loc.altitude), + MGLEventKeyHorizontalAccuracy: @(loc.horizontalAccuracy), MGLEventKeyVerticalAccuracy: @(loc.verticalAccuracy) }]; } diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index 6456e51538..8b4f46deb5 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -31,13 +31,14 @@ void LiveTileData::parse() { return; } - try { - if (!style) { - throw std::runtime_error("style isn't present in LiveTileData object anymore"); - } + const LiveTile* tile = annotationManager.getTile(id); + + if (tile) { + try { + if (!style) { + throw std::runtime_error("style isn't present in LiveTileData object anymore"); + } - const LiveTile* tile = annotationManager.getTile(id); - if (tile) { // Parsing creates state that is encapsulated in TileParser. While parsing, // the TileParser object writes results into this objects. All other state // is going to be discarded afterwards. @@ -47,13 +48,16 @@ void LiveTileData::parse() { style.reset(); parser.parse(); - } else { + } catch (const std::exception& ex) { + Log::Error(Event::ParseTile, "Live-parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what()); state = State::obsolete; + return; } - } catch (const std::exception& ex) { - Log::Error(Event::ParseTile, "Live-parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what()); + } else { + // Clear the style so that we don't have a cycle in the shared_ptr references. + style.reset(); + state = State::obsolete; - return; } if (state != State::obsolete) { diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index f76845e3a7..adaf22d60f 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -818,3 +818,26 @@ void Map::render() { triggerUpdate(); } } + +void Map::setSourceTileCacheSize(size_t size) { + if (size != getSourceTileCacheSize()) { + invokeTask([=] { + sourceCacheSize = size; + if (!style) return; + for (const auto &source : style->sources) { + source->setCacheSize(sourceCacheSize); + } + env->performCleanup(); + }); + } +} + +void Map::onLowMemory() { + invokeTask([=] { + if (!style) return; + for (const auto &source : style->sources) { + source->onLowMemory(); + } + env->performCleanup(); + }); +}; diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 29f84171d1..3245bab2e3 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -245,6 +245,10 @@ TileData::State Source::addTile(Map &map, Worker &worker, } if (!new_tile.data) { + new_tile.data = cache.get(id.to_uint64()); + } + + if (!new_tile.data) { // If we don't find working tile data, we're just going to load it. if (info.type == SourceType::Vector) { new_tile.data = @@ -394,20 +398,33 @@ void Source::update(Map &map, } } + if (info.type != SourceType::Raster && cache.getSize() == 0) { + size_t conservativeCacheSize = ((float)map.getState().getWidth() / util::tileSize) * + ((float)map.getState().getHeight() / util::tileSize) * + (map.getMaxZoom() - map.getMinZoom() + 1) * + 0.5; + cache.setSize(conservativeCacheSize); + } + + auto& tileCache = cache; + auto& type = info.type; + // Remove tiles that we definitely don't need, i.e. tiles that are not on // the required list. std::set<TileID> retain_data; - util::erase_if(tiles, [&retain, &retain_data](std::pair<const TileID, std::unique_ptr<Tile>> &pair) { + util::erase_if(tiles, [&retain, &retain_data, &tileCache, &type](std::pair<const TileID, std::unique_ptr<Tile>> &pair) { Tile &tile = *pair.second; bool obsolete = std::find(retain.begin(), retain.end(), tile.id) == retain.end(); if (!obsolete) { retain_data.insert(tile.data->id); + } else if (type != SourceType::Raster && tile.data->ready()) { + tileCache.add(tile.id.to_uint64(), tile.data); } return obsolete; }); // Remove all the expired pointers from the set. - util::erase_if(tile_data, [&retain_data](std::pair<const TileID, std::weak_ptr<TileData>> &pair) { + util::erase_if(tile_data, [&retain_data, &tileCache](std::pair<const TileID, std::weak_ptr<TileData>> &pair) { const util::ptr<TileData> tile = pair.second.lock(); if (!tile) { return true; @@ -415,7 +432,9 @@ void Source::update(Map &map, bool obsolete = retain_data.find(tile->id) == retain_data.end(); if (obsolete) { - tile->cancel(); + if (!tileCache.has(tile->id.to_uint64())) { + tile->cancel(); + } return true; } else { return false; @@ -426,10 +445,19 @@ void Source::update(Map &map, } void Source::invalidateTiles(const std::vector<TileID>& ids) { + cache.clear(); for (auto& id : ids) { tiles.erase(id); tile_data.erase(id); } } +void Source::setCacheSize(size_t size) { + cache.setSize(size); +} + +void Source::onLowMemory() { + cache.clear(); +} + } diff --git a/src/mbgl/map/source.hpp b/src/mbgl/map/source.hpp index 625647ac5e..035e862284 100644 --- a/src/mbgl/map/source.hpp +++ b/src/mbgl/map/source.hpp @@ -3,6 +3,7 @@ #include <mbgl/map/tile_id.hpp> #include <mbgl/map/tile_data.hpp> +#include <mbgl/map/tile_cache.hpp> #include <mbgl/style/types.hpp> #include <mbgl/util/noncopyable.hpp> @@ -72,6 +73,9 @@ public: std::forward_list<Tile *> getLoadedTiles() const; + void setCacheSize(size_t); + void onLowMemory(); + SourceInfo info; bool enabled; @@ -96,6 +100,7 @@ private: std::map<TileID, std::unique_ptr<Tile>> tiles; std::map<TileID, std::weak_ptr<TileData>> tile_data; + TileCache cache; }; } diff --git a/src/mbgl/map/tile_cache.cpp b/src/mbgl/map/tile_cache.cpp new file mode 100644 index 0000000000..71eb500be6 --- /dev/null +++ b/src/mbgl/map/tile_cache.cpp @@ -0,0 +1,60 @@ +#include <mbgl/map/tile_cache.hpp> + +#include <cassert> + +namespace mbgl { + +void TileCache::setSize(size_t size_) { + size = size_; + + while (orderedKeys.size() > size) { + auto key = orderedKeys.front(); + orderedKeys.pop_front(); + tiles.erase(key); + } + + assert(orderedKeys.size() <= size); + + tiles.reserve(size); + orderedKeys.resize(size); +} + +void TileCache::add(uint64_t key, std::shared_ptr<TileData> data) { + + assert(tiles.find(key) == tiles.end()); + + tiles.emplace(key, data); + orderedKeys.push_back(key); + + if (orderedKeys.size() > size) { + get(orderedKeys.front()); + } + + assert(orderedKeys.size() <= size); +}; + +std::shared_ptr<TileData> TileCache::get(uint64_t key) { + + std::shared_ptr<TileData> data; + + auto it = tiles.find(key); + if (it != tiles.end()) { + data = it->second; + tiles.erase(it); + orderedKeys.remove(key); + assert(data->ready()); + } + + return data; +}; + +bool TileCache::has(uint64_t key) { + return tiles.find(key) != tiles.end(); +} + +void TileCache::clear() { + orderedKeys.clear(); + tiles.clear(); +} + +}; diff --git a/src/mbgl/map/tile_cache.hpp b/src/mbgl/map/tile_cache.hpp new file mode 100644 index 0000000000..26d830c123 --- /dev/null +++ b/src/mbgl/map/tile_cache.hpp @@ -0,0 +1,30 @@ +#ifndef MBGL_MAP_TILE_CACHE +#define MBGL_MAP_TILE_CACHE + +#include <mbgl/map/tile_data.hpp> + +#include <list> +#include <unordered_map> + +namespace mbgl { + +class TileCache { +public: + TileCache(size_t size_ = 0) : size(size_) {} + + void setSize(size_t); + size_t getSize() const { return size; }; + void add(uint64_t key, std::shared_ptr<TileData> data); + std::shared_ptr<TileData> get(uint64_t key); + bool has(uint64_t key); + void clear(); +private: + std::unordered_map<uint64_t, std::shared_ptr<TileData>> tiles; + std::list<uint64_t> orderedKeys; + + size_t size; +}; + +}; + +#endif diff --git a/src/mbgl/map/tile_data.cpp b/src/mbgl/map/tile_data.cpp index 72e356bbf2..bb8d18d12f 100644 --- a/src/mbgl/map/tile_data.cpp +++ b/src/mbgl/map/tile_data.cpp @@ -64,5 +64,9 @@ void TileData::reparse(Worker& worker, std::function<void()> callback) { EnvironmentScope scope(tile->env, ThreadType::TileWorker, "TileWorker_" + tile->name); tile->parse(); }, - callback); + [tile, callback]() { + // `tile` is bound in this lambda to ensure that if it's the last owning pointer, + // destruction happens on the map thread, not the worker thread. + callback(); + }); } diff --git a/styles b/styles -Subproject 890d7dd5a18f06a8e475eaf9e2dcc67456ad3b2 +Subproject 86aecb8e997c54c9d2bf6ac494fea132e375ad0 |