diff options
author | Justin R. Miller <incanus@codesorcery.net> | 2015-03-27 09:00:07 -0700 |
---|---|---|
committer | Justin R. Miller <incanus@codesorcery.net> | 2015-03-27 09:00:07 -0700 |
commit | 2066e201ea5b90cc804c68c4e1cc8fb7eb5bea35 (patch) | |
tree | 0f5aa56590fee5fbea85eabbb39452dff6410e8d | |
parent | 1a8d6445d18741b399f381e3835c2362286582f6 (diff) | |
parent | 64b60faced2cc3b90aa69813cda369e34eb88f03 (diff) | |
download | qtlocation-mapboxgl-2066e201ea5b90cc804c68c4e1cc8fb7eb5bea35.tar.gz |
Merge remote-tracking branch 'origin/master' into 1128-convert-booleans
-rw-r--r-- | include/mbgl/ios/MGLMapboxEvents.h | 30 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 15 | ||||
-rw-r--r-- | platform/ios/MGLMapView.mm | 44 | ||||
-rw-r--r-- | platform/ios/MGLMapboxEvents.m | 40 | ||||
-rw-r--r-- | platform/ios/MGLMetricsLocationManager.m | 6 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 87 |
6 files changed, 148 insertions, 74 deletions
diff --git a/include/mbgl/ios/MGLMapboxEvents.h b/include/mbgl/ios/MGLMapboxEvents.h index 6f994fea26..0567eb6764 100644 --- a/include/mbgl/ios/MGLMapboxEvents.h +++ b/include/mbgl/ios/MGLMapboxEvents.h @@ -1,16 +1,24 @@ #import <Foundation/Foundation.h> -extern NSString *const MGLEventMapLoad; -extern NSString *const MGLEventMapTap; -extern NSString *const MGLEventMapSingleTap; -extern NSString *const MGLEventMapDoubleTap; -extern NSString *const MGLEventMapTwoFingerSingleTap; -extern NSString *const MGLEventMapQuickZoom; -extern NSString *const MGLEventMapPanStart; -extern NSString *const MGLEventMapPanEnd; -extern NSString *const MGLEventMapPinchStart; -extern NSString *const MGLEventMapRotateStart; -extern NSString *const MGLEventMapLocation; +extern NSString *const MGLEventTypeMapLoad; +extern NSString *const MGLEventTypeMapTap; +extern NSString *const MGLEventTypeMapDragEnd; +extern NSString *const MGLEventTypeLocation; + +extern NSString *const MGLEventKeyLatitude; +extern NSString *const MGLEventKeyLongitude; +extern NSString *const MGLEventKeyZoomLevel; +extern NSString *const MGLEventKeyPushEnabled; +extern NSString *const MGLEventKeyEmailEnabled; +extern NSString *const MGLEventKeyGestureID; + +extern NSString *const MGLEventGestureSingleTap; +extern NSString *const MGLEventGestureDoubleTap; +extern NSString *const MGLEventGestureTwoFingerSingleTap; +extern NSString *const MGLEventGestureQuickZoom; +extern NSString *const MGLEventGesturePanStart; +extern NSString *const MGLEventGesturePinchStart; +extern NSString *const MGLEventGestureRotateStart; @interface MGLMapboxEvents : NSObject diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index cb93916284..4ce7014307 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -15,6 +15,7 @@ #include <iosfwd> #include <set> #include <vector> +#include <queue> #include <mutex> #include <condition_variable> #include <functional> @@ -159,8 +160,8 @@ public: const std::vector<std::string>& symbols); void removeAnnotation(uint32_t); void removeAnnotations(const std::vector<uint32_t>&); - std::vector<uint32_t> getAnnotationsInBounds(const LatLngBounds&) const; - LatLngBounds getBoundsForAnnotations(const std::vector<uint32_t>&) const; + std::vector<uint32_t> getAnnotationsInBounds(const LatLngBounds&); + LatLngBounds getBoundsForAnnotations(const std::vector<uint32_t>&); // Debug void setDebug(bool value); @@ -200,6 +201,12 @@ private: // the stylesheet. void prepare(); + // Runs the function in the map thread. + void invokeTask(std::function<void()>&&); + template <typename Fn> auto invokeSyncTask(const Fn& fn) -> decltype(fn()); + + void processTasks(); + void updateAnnotationTiles(const std::vector<Tile::ID>&); enum class Mode : uint8_t { @@ -219,6 +226,7 @@ private: std::thread thread; std::unique_ptr<uv::async> asyncTerminate; std::unique_ptr<uv::async> asyncUpdate; + std::unique_ptr<uv::async> asyncInvoke; std::unique_ptr<uv::async> asyncRender; bool terminating = false; @@ -257,6 +265,9 @@ private: std::set<util::ptr<StyleSource>> activeSources; std::atomic<UpdateType> updated; + + std::mutex mutexTask; + std::queue<std::function<void()>> tasks; }; } diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 31d84000ac..6f3aec8038 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -355,12 +355,12 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; const mbgl::LatLng latLng = mbglMap->getLatLng(); const double zoom = mbglMap->getZoom(); - [MGLMapboxEvents pushEvent:MGLEventMapLoad withAttributes:@{ - @"lat": @(latLng.latitude), - @"lng": @(latLng.longitude), - @"zoom": @(zoom), - @"enabled.push": @([MGLMapboxEvents checkPushEnabled]), - @"enabled.email": @([MGLMapboxEvents checkEmailEnabled]) + [MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{ + MGLEventKeyLatitude: @(latLng.latitude), + MGLEventKeyLongitude: @(latLng.longitude), + MGLEventKeyZoomLevel: @(zoom), + MGLEventKeyPushEnabled: @([MGLMapboxEvents checkPushEnabled]), + MGLEventKeyEmailEnabled: @([MGLMapboxEvents checkEmailEnabled]) }]; return YES; @@ -586,7 +586,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handlePanGesture:(UIPanGestureRecognizer *)pan { - [self trackGestureEvent:MGLEventMapPanStart forRecognizer:pan]; + [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan]; if ( ! self.isScrollEnabled) return; @@ -653,17 +653,17 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; CLLocationCoordinate2D panCoordinate = [self convertPoint:pointInView toCoordinateFromView:pan.view]; double zoom = [self zoomLevel]; - [MGLMapboxEvents pushEvent:MGLEventMapPanEnd withAttributes:@{ - @"lat": @(panCoordinate.latitude), - @"lng": @(panCoordinate.longitude), - @"zoom": @(zoom) + [MGLMapboxEvents pushEvent:MGLEventTypeMapDragEnd withAttributes:@{ + MGLEventKeyLatitude: @(panCoordinate.latitude), + MGLEventKeyLongitude: @(panCoordinate.longitude), + MGLEventKeyZoomLevel: @(zoom) }]; } } - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch { - [self trackGestureEvent:MGLEventMapPinchStart forRecognizer:pinch]; + [self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch]; if ( ! self.isZoomEnabled) return; @@ -701,7 +701,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate { - [self trackGestureEvent:MGLEventMapRotateStart forRecognizer:rotate]; + [self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate]; if ( ! self.isRotateEnabled) return; @@ -743,7 +743,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap { - [self trackGestureEvent:MGLEventMapSingleTap forRecognizer:singleTap]; + [self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap]; CGPoint tapPoint = [singleTap locationInView:self]; @@ -866,7 +866,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap { - [self trackGestureEvent:MGLEventMapDoubleTap forRecognizer:doubleTap]; + [self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap]; if ( ! self.isZoomEnabled) return; @@ -897,7 +897,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap { - [self trackGestureEvent:MGLEventMapTwoFingerSingleTap forRecognizer:twoFingerTap]; + [self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap]; if ( ! self.isZoomEnabled) return; @@ -930,7 +930,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom { - [self trackGestureEvent:MGLEventMapQuickZoom forRecognizer:quickZoom]; + [self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom]; if ( ! self.isZoomEnabled) return; @@ -984,11 +984,11 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; CLLocationCoordinate2D gestureCoordinate = [self convertPoint:pointInView toCoordinateFromView:recognizer.view]; double zoom = [self zoomLevel]; - [MGLMapboxEvents pushEvent:MGLEventMapTap withAttributes:@{ - @"lat": @(gestureCoordinate.latitude), - @"lng": @(gestureCoordinate.longitude), - @"zoom": @(zoom), - @"gesture": gestureID + [MGLMapboxEvents pushEvent:MGLEventTypeMapTap withAttributes:@{ + MGLEventKeyLatitude: @(gestureCoordinate.latitude), + MGLEventKeyLongitude: @(gestureCoordinate.longitude), + MGLEventKeyZoomLevel: @(zoom), + MGLEventKeyGestureID: gestureID }]; } diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 1ce8288f5d..94374b9da9 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -12,17 +12,25 @@ static NSString *const MGLMapboxEventsUserAgent = @"MapboxEventsiOS/1.0"; static NSString *const MGLMapboxEventsAPIBase = @"https://api.tiles.mapbox.com"; -NSString *const MGLEventMapLoad = @"map.load"; -NSString *const MGLEventMapTap = @"map.click"; -NSString *const MGLEventMapSingleTap = @"SingleTap"; -NSString *const MGLEventMapDoubleTap = @"DoubleTap"; -NSString *const MGLEventMapTwoFingerSingleTap = @"TwoFingerTap"; -NSString *const MGLEventMapQuickZoom = @"QuickZoom"; -NSString *const MGLEventMapPanStart = @"Pan"; -NSString *const MGLEventMapPanEnd = @"map.dragend"; -NSString *const MGLEventMapPinchStart = @"Pinch"; -NSString *const MGLEventMapRotateStart = @"Rotation"; -NSString *const MGLEventMapLocation = @"Location"; +NSString *const MGLEventTypeMapLoad = @"map.load"; +NSString *const MGLEventTypeMapTap = @"map.click"; +NSString *const MGLEventTypeMapDragEnd = @"map.dragend"; +NSString *const MGLEventTypeLocation = @"Location"; + +NSString *const MGLEventKeyLatitude = @"lat"; +NSString *const MGLEventKeyLongitude = @"lng"; +NSString *const MGLEventKeyZoomLevel = @"zoom"; +NSString *const MGLEventKeyPushEnabled = @"enabled.push"; +NSString *const MGLEventKeyEmailEnabled = @"enabled.email"; +NSString *const MGLEventKeyGestureID = @"gesture"; + +NSString *const MGLEventGestureSingleTap = @"SingleTap"; +NSString *const MGLEventGestureDoubleTap = @"DoubleTap"; +NSString *const MGLEventGestureTwoFingerSingleTap = @"TwoFingerTap"; +NSString *const MGLEventGestureQuickZoom = @"QuickZoom"; +NSString *const MGLEventGesturePanStart = @"Pan"; +NSString *const MGLEventGesturePinchStart = @"Pinch"; +NSString *const MGLEventGestureRotateStart = @"Rotation"; // // Threadsafety conventions: @@ -216,7 +224,7 @@ NSString *const MGLEventMapLocation = @"Location"; // use of +pushEvent:withAttributes:. // - (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary { - // convert any BOOL types to string values written out like JS + // conve+rt any BOOL types to string values written out like JS NSMutableDictionary *newAttributeDictionary = [NSMutableDictionary dictionaryWithCapacity:[attributeDictionary count]]; NSString *key; NSObject *value; @@ -249,7 +257,7 @@ NSString *const MGLEventMapLocation = @"Location"; if (!event) return; - NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; + NSMutableDictionary *evt = [[NSMutableDictionary alloc] initWithDictionary:attributeDictionary]; // mapbox-events stock attributes [evt setObject:event forKey:@"event"]; [evt setObject:@(1) forKey:@"version"]; @@ -268,11 +276,7 @@ NSString *const MGLEventMapLocation = @"Location"; [evt setValue:[weakSelf getCurrentCellularNetworkConnectionType] forKey:@"cellularNetworkType"]; [evt setValue:[weakSelf getWifiNetworkName] forKey:@"wifi"]; [evt setValue:@([weakSelf getContentSizeScale]) forKey:@"accessibilityFontScale"]; - - for (NSString *key in [attributeDictionary allKeys]) { - [evt setObject:[attributeDictionary valueForKey:key] forKey:key]; - } - + // Make Immutable Version NSDictionary *finalEvent = [NSDictionary dictionaryWithDictionary:evt]; diff --git a/platform/ios/MGLMetricsLocationManager.m b/platform/ios/MGLMetricsLocationManager.m index bdf6e14ae9..c0ff740b3a 100644 --- a/platform/ios/MGLMetricsLocationManager.m +++ b/platform/ios/MGLMetricsLocationManager.m @@ -43,9 +43,9 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { // Iterate through locations to pass all data for (CLLocation *loc in locations) { - [MGLMapboxEvents pushEvent:MGLEventMapLocation withAttributes:@{ - @"lat": @(loc.coordinate.latitude), - @"lng": @(loc.coordinate.longitude) + [MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{ + MGLEventKeyLatitude: @(loc.coordinate.latitude), + MGLEventKeyLongitude: @(loc.coordinate.longitude) }]; } } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index a49df01191..47d6ed71d1 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -144,6 +144,11 @@ void Map::start(bool startPaused) { update(); }); + asyncInvoke = util::make_unique<uv::async>(env->loop, [this] { + processTasks(); + }); + + asyncRender = util::make_unique<uv::async>(env->loop, [this] { // Must be called in Map thread. assert(Environment::currentlyOn(ThreadType::Map)); @@ -315,6 +320,42 @@ void Map::triggerRender() { asyncRender->send(); } +// Runs the function in the map thread. +void Map::invokeTask(std::function<void()>&& fn) { + { + std::lock_guard<std::mutex> lock(mutexTask); + tasks.emplace(::std::forward<std::function<void()>>(fn)); + } + + // TODO: Once we have aligned static and continuous rendering, this should always dispatch + // to the async queue. + if (asyncInvoke) { + asyncInvoke->send(); + } else { + processTasks(); + } +} + +template <typename Fn> auto Map::invokeSyncTask(const Fn& fn) -> decltype(fn()) { + std::promise<decltype(fn())> promise; + invokeTask([&fn, &promise] { promise.set_value(fn()); }); + return promise.get_future().get(); +} + +// Processes the functions that should be run in the map thread. +void Map::processTasks() { + std::queue<std::function<void()>> queue; + { + std::lock_guard<std::mutex> lock(mutexTask); + queue.swap(tasks); + } + + while (!queue.empty()) { + queue.front()(); + queue.pop(); + } +} + void Map::checkForPause() { std::unique_lock<std::mutex> lockRun (mutexRun); while (pausing) { @@ -542,27 +583,31 @@ std::string Map::getAccessToken() const { void Map::setDefaultPointAnnotationSymbol(const std::string& symbol) { assert(Environment::currentlyOn(ThreadType::Main)); - annotationManager->setDefaultPointAnnotationSymbol(symbol); + invokeTask([=] { + annotationManager->setDefaultPointAnnotationSymbol(symbol); + }); } double Map::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) { - SpritePosition pos = sprite->getSpritePosition(symbol); - - return -pos.height / pos.pixelRatio / 2; + assert(Environment::currentlyOn(ThreadType::Main)); + return invokeSyncTask([&] { + assert(sprite); + const SpritePosition pos = sprite->getSpritePosition(symbol); + return -pos.height / pos.pixelRatio / 2; + }); } uint32_t Map::addPointAnnotation(const LatLng& point, const std::string& symbol) { - assert(Environment::currentlyOn(ThreadType::Main)); - std::vector<LatLng> points({ point }); - std::vector<std::string> symbols({ symbol }); - return addPointAnnotations(points, symbols)[0]; + return addPointAnnotations({ point }, { symbol }).front(); } std::vector<uint32_t> Map::addPointAnnotations(const std::vector<LatLng>& points, const std::vector<std::string>& symbols) { assert(Environment::currentlyOn(ThreadType::Main)); - auto result = annotationManager->addPointAnnotations(points, symbols, *this); - updateAnnotationTiles(result.first); - return result.second; + return invokeSyncTask([&] { + auto result = annotationManager->addPointAnnotations(points, symbols, *this); + updateAnnotationTiles(result.first); + return result.second; + }); } void Map::removeAnnotation(uint32_t annotation) { @@ -572,22 +617,28 @@ void Map::removeAnnotation(uint32_t annotation) { void Map::removeAnnotations(const std::vector<uint32_t>& annotations) { assert(Environment::currentlyOn(ThreadType::Main)); - auto result = annotationManager->removeAnnotations(annotations, *this); - updateAnnotationTiles(result); + invokeTask([=] { + auto result = annotationManager->removeAnnotations(annotations, *this); + updateAnnotationTiles(result); + }); } -std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds) const { +std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds) { assert(Environment::currentlyOn(ThreadType::Main)); - return annotationManager->getAnnotationsInBounds(bounds, *this); + return invokeSyncTask([&] { + return annotationManager->getAnnotationsInBounds(bounds, *this); + }); } -LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotations) const { +LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotations) { assert(Environment::currentlyOn(ThreadType::Main)); - return annotationManager->getBoundsForAnnotations(annotations); + return invokeSyncTask([&] { + return annotationManager->getBoundsForAnnotations(annotations); + }); } void Map::updateAnnotationTiles(const std::vector<Tile::ID>& ids) { - assert(Environment::currentlyOn(ThreadType::Main)); + assert(Environment::currentlyOn(ThreadType::Map)); for (const auto &source : activeSources) { if (source->info.type == SourceType::Annotations) { source->source->invalidateTiles(*this, ids); |