summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2017-04-04 11:33:22 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-04-13 10:33:18 -0700
commit7b041b123cb067d247a727bb3a4563bb2fc575eb (patch)
treecdf9ce1583ef6cc3a16970a7ad9a1527521ecf41
parentde6c9b35f35f6ec0950529261b207d716c046beb (diff)
downloadqtlocation-mapboxgl-7b041b123cb067d247a727bb3a4563bb2fc575eb.tar.gz
[core, darwin] Object identity for MGLSource*, MGLStyleLayer*
All `MGLSource` pointers referencing the same logical source will now be object identical; similarly for `MGLStyleLayer`.
-rw-r--r--CMakeLists.txt1
-rw-r--r--cmake/core.cmake1
-rw-r--r--cmake/test.cmake1
-rw-r--r--include/mbgl/style/layer.hpp6
-rw-r--r--include/mbgl/style/source.hpp6
-rw-r--r--include/mbgl/util/any.hpp10
-rw-r--r--platform/darwin/src/MGLSource.mm1
-rw-r--r--platform/darwin/src/MGLSource_Private.h8
-rw-r--r--platform/darwin/src/MGLStyle.mm41
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm1
-rw-r--r--platform/darwin/src/MGLStyleLayer_Private.h8
-rw-r--r--platform/darwin/test/MGLStyleTests.mm2
12 files changed, 66 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6ed681bde..9e7ee314e7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,7 @@ set_source_files_properties(src/mbgl/util/version.cpp PROPERTIES COMPILE_DEFINIT
mason_use(geometry VERSION 0.9.0 HEADER_ONLY)
mason_use(variant VERSION 1.1.4 HEADER_ONLY)
+mason_use(any VERSION 8fef1e9 HEADER_ONLY)
mason_use(unique_resource VERSION cba309e HEADER_ONLY)
mason_use(rapidjson VERSION 1.1.0 HEADER_ONLY)
mason_use(boost VERSION 1.62.0 HEADER_ONLY)
diff --git a/cmake/core.cmake b/cmake/core.cmake
index 616e43028c..531edc092d 100644
--- a/cmake/core.cmake
+++ b/cmake/core.cmake
@@ -14,6 +14,7 @@ target_include_directories(mbgl-core
target_add_mason_package(mbgl-core PUBLIC geometry)
target_add_mason_package(mbgl-core PUBLIC variant)
+target_add_mason_package(mbgl-core PUBLIC any)
target_add_mason_package(mbgl-core PRIVATE unique_resource)
target_add_mason_package(mbgl-core PRIVATE rapidjson)
target_add_mason_package(mbgl-core PRIVATE boost)
diff --git a/cmake/test.cmake b/cmake/test.cmake
index 5e77de2448..3c63f7bcf8 100644
--- a/cmake/test.cmake
+++ b/cmake/test.cmake
@@ -27,6 +27,7 @@ target_link_libraries(mbgl-test
target_add_mason_package(mbgl-test PRIVATE geometry)
target_add_mason_package(mbgl-test PRIVATE variant)
+target_add_mason_package(mbgl-test PRIVATE any)
target_add_mason_package(mbgl-test PRIVATE unique_resource)
target_add_mason_package(mbgl-test PRIVATE rapidjson)
target_add_mason_package(mbgl-test PRIVATE gtest)
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index 670faa8254..fa88b30dbc 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/any.hpp>
#include <mbgl/style/types.hpp>
#include <memory>
@@ -118,6 +119,11 @@ public:
// Private implementation
const std::unique_ptr<Impl> baseImpl;
+ // For use in SDK bindings, which store a reference to a platform-native peer
+ // object here, so that separately-obtained references to this object share
+ // identical platform-native peers.
+ any peer;
+
friend std::string layoutKey(const Layer&);
};
diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp
index 0e6e32b112..f2dfb6a896 100644
--- a/include/mbgl/style/source.hpp
+++ b/include/mbgl/style/source.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/range.hpp>
+#include <mbgl/util/any.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/style/query.hpp>
@@ -64,6 +65,11 @@ public:
class Impl;
const std::unique_ptr<Impl> baseImpl;
+ // For use in SDK bindings, which store a reference to a platform-native peer
+ // object here, so that separately-obtained references to this object share
+ // identical platform-native peers.
+ any peer;
+
protected:
const SourceType type;
Source(SourceType, std::unique_ptr<Impl>);
diff --git a/include/mbgl/util/any.hpp b/include/mbgl/util/any.hpp
new file mode 100644
index 0000000000..eea64b188a
--- /dev/null
+++ b/include/mbgl/util/any.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <linb/any.hpp>
+
+namespace mbgl {
+
+using linb::any;
+using linb::any_cast;
+
+} // namespace mbgl
diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm
index 1940db688c..59c2ae13e6 100644
--- a/platform/darwin/src/MGLSource.mm
+++ b/platform/darwin/src/MGLSource.mm
@@ -29,6 +29,7 @@
NSString *identifier = @(rawSource->getID().c_str());
if (self = [self initWithIdentifier:identifier]) {
_rawSource = rawSource;
+ _rawSource->peer = SourceWrapper { self };
}
return self;
}
diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h
index 2fc170b86b..6f86e4800b 100644
--- a/platform/darwin/src/MGLSource_Private.h
+++ b/platform/darwin/src/MGLSource_Private.h
@@ -10,6 +10,14 @@ namespace mbgl {
}
}
+// A struct to be stored in the `peer` member of mbgl::style::Source, in order to implement
+// object identity. We don't store a MGLSource pointer directly because that doesn't
+// interoperate with ARC. The inner pointer is weak in order to avoid a reference cycle for
+// "pending" MGLSources, which have a strong owning pointer to the mbgl::style::Source.
+struct SourceWrapper {
+ __weak MGLSource *source;
+};
+
@class MGLMapView;
@interface MGLSource (Private)
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 83ff73e8f9..b01d9aa513 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -166,17 +166,21 @@ static NSURL *MGLStyleURL_emerald;
return rawSource ? [self sourceFromMBGLSource:rawSource] : nil;
}
-- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)source {
+- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)rawSource {
+ if (MGLSource *source = rawSource->peer.empty() ? nil : mbgl::any_cast<SourceWrapper>(rawSource->peer).source) {
+ return source;
+ }
+
// TODO: Fill in options specific to the respective source classes
// https://github.com/mapbox/mapbox-gl-native/issues/6584
- if (auto vectorSource = source->as<mbgl::style::VectorSource>()) {
+ if (auto vectorSource = rawSource->as<mbgl::style::VectorSource>()) {
return [[MGLVectorSource alloc] initWithRawSource:vectorSource];
- } else if (auto geoJSONSource = source->as<mbgl::style::GeoJSONSource>()) {
+ } else if (auto geoJSONSource = rawSource->as<mbgl::style::GeoJSONSource>()) {
return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource];
- } else if (auto rasterSource = source->as<mbgl::style::RasterSource>()) {
+ } else if (auto rasterSource = rawSource->as<mbgl::style::RasterSource>()) {
return [[MGLRasterSource alloc] initWithRawSource:rasterSource];
} else {
- return [[MGLSource alloc] initWithRawSource:source];
+ return [[MGLSource alloc] initWithRawSource:rawSource];
}
}
@@ -319,35 +323,32 @@ static NSURL *MGLStyleURL_emerald;
[styleLayer removeFromMapView:self.mapView];
}
-- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer
+- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)rawLayer
{
- NSParameterAssert(mbglLayer);
+ NSParameterAssert(rawLayer);
- NSString *identifier = @(mbglLayer->getID().c_str());
+ if (MGLStyleLayer *layer = rawLayer->peer.empty() ? nil : mbgl::any_cast<LayerWrapper>(rawLayer->peer).layer) {
+ return layer;
+ }
- if (auto fillLayer = mbglLayer->as<mbgl::style::FillLayer>()) {
+ if (auto fillLayer = rawLayer->as<mbgl::style::FillLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(fillLayer->getSourceID().c_str())];
return [[MGLFillStyleLayer alloc] initWithRawLayer:fillLayer source:source];
- } else if (auto lineLayer = mbglLayer->as<mbgl::style::LineLayer>()) {
+ } else if (auto lineLayer = rawLayer->as<mbgl::style::LineLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(lineLayer->getSourceID().c_str())];
return [[MGLLineStyleLayer alloc] initWithRawLayer:lineLayer source:source];
- } else if (auto symbolLayer = mbglLayer->as<mbgl::style::SymbolLayer>()) {
+ } else if (auto symbolLayer = rawLayer->as<mbgl::style::SymbolLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(symbolLayer->getSourceID().c_str())];
return [[MGLSymbolStyleLayer alloc] initWithRawLayer:symbolLayer source:source];
- } else if (auto rasterLayer = mbglLayer->as<mbgl::style::RasterLayer>()) {
+ } else if (auto rasterLayer = rawLayer->as<mbgl::style::RasterLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(rasterLayer->getSourceID().c_str())];
return [[MGLRasterStyleLayer alloc] initWithRawLayer:rasterLayer source:source];
- } else if (auto circleLayer = mbglLayer->as<mbgl::style::CircleLayer>()) {
+ } else if (auto circleLayer = rawLayer->as<mbgl::style::CircleLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(circleLayer->getSourceID().c_str())];
return [[MGLCircleStyleLayer alloc] initWithRawLayer:circleLayer source:source];
- } else if (auto backgroundLayer = mbglLayer->as<mbgl::style::BackgroundLayer>()) {
+ } else if (auto backgroundLayer = rawLayer->as<mbgl::style::BackgroundLayer>()) {
return [[MGLBackgroundStyleLayer alloc] initWithRawLayer:backgroundLayer];
- } else if (auto customLayer = mbglLayer->as<mbgl::style::CustomLayer>()) {
- MGLStyleLayer *styleLayer = self.openGLLayers[identifier];
- if (styleLayer) {
- NSAssert(styleLayer.rawLayer == customLayer, @"%@ wraps a CustomLayer that differs from the one associated with the underlying style.", styleLayer);
- return styleLayer;
- }
+ } else if (auto customLayer = rawLayer->as<mbgl::style::CustomLayer>()) {
return [[MGLOpenGLStyleLayer alloc] initWithRawLayer:customLayer];
} else {
NSAssert(NO, @"Unrecognized layer type");
diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm
index c72541526f..4bfaea934b 100644
--- a/platform/darwin/src/MGLStyleLayer.mm
+++ b/platform/darwin/src/MGLStyleLayer.mm
@@ -18,6 +18,7 @@
if (self = [super init]) {
_identifier = @(rawLayer->getID().c_str());
_rawLayer = rawLayer;
+ _rawLayer->peer = LayerWrapper { self };
}
return self;
}
diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h
index d024a0bb13..ed8ec31755 100644
--- a/platform/darwin/src/MGLStyleLayer_Private.h
+++ b/platform/darwin/src/MGLStyleLayer_Private.h
@@ -7,6 +7,14 @@
NS_ASSUME_NONNULL_BEGIN
+// A struct to be stored in the `peer` member of mbgl::style::Layer, in order to implement
+// object identity. We don't store a MGLStyleLayer pointer directly because that doesn't
+// interoperate with ARC. The inner pointer is weak in order to avoid a reference cycle for
+// "pending" MGLStyleLayers, which have a strong owning pointer to the mbgl::style::Layer.
+struct LayerWrapper {
+ __weak MGLStyleLayer *layer;
+};
+
/**
Assert that the style layer is valid.
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index 36772e556d..f9598a143d 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -148,6 +148,7 @@
MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"shapeSource" shape:nil options:nil];
[self.style addSource:shapeSource];
XCTAssertEqual(self.style.sources.count, initialSources.count + 1);
+ XCTAssertEqual(shapeSource, [self.style sourceWithIdentifier:@"shapeSource"]);
[self.style removeSource:shapeSource];
XCTAssertEqual(self.style.sources.count, initialSources.count);
}
@@ -238,6 +239,7 @@
MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:shapeSource];
[self.style addLayer:fillLayer];
XCTAssertEqual(self.style.layers.count, initialLayers.count + 1);
+ XCTAssertEqual(fillLayer, [self.style layerWithIdentifier:@"fillLayer"]);
[self.style removeLayer:fillLayer];
XCTAssertEqual(self.style.layers.count, initialLayers.count);
}