Skip to content

Commit 8e82b26

Browse files
committed
Manual memory management
1 parent 7168248 commit 8e82b26

File tree

6 files changed

+58
-12
lines changed

6 files changed

+58
-12
lines changed

README.md

+24-3
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,33 @@ cd ios && pod install
1919
## Usage
2020

2121
```js
22-
import Clusterer from "react-native-clusterer";
22+
import Clusterer from 'react-native-clusterer';
2323

2424
// ...
2525

2626
const supercluster = new Clusterer(points, options);
27+
const clusters = supercluster.getTile(2, 1, 2)
28+
29+
// ...
30+
// Don't forget to clean up to free memory
31+
// Most likely implementation (on component unmount)
32+
useEffect(() => {
33+
// ...
34+
return () => {
35+
supercluster.destroy();
36+
// ...
37+
};
38+
}, []);
2739
```
40+
2841
#### Points
2942

3043
Array of [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) objects. Each feature's `geometry` must be a [GeoJSON Point](https://tools.ietf.org/html/rfc7946#section-3.1.2). Once loaded, index is immutable.
3144

3245
#### Options
3346

3447
| Option | Default | Description |
35-
|------------|---------|-------------------------------------------------------------------|
48+
| ---------- | ------- | ----------------------------------------------------------------- |
3649
| minZoom | 0 | Minimum zoom level at which clusters are generated. |
3750
| maxZoom | 16 | Maximum zoom level at which clusters are generated. |
3851
| minPoints | 2 | Minimum number of points to form a cluster. |
@@ -43,7 +56,9 @@ Array of [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) obje
4356
## Methods
4457

4558
#### `getClusters(bbox, zoom)`
59+
4660
TO-DO
61+
4762
<!-- For the given `bbox` array (`[westLng, southLat, eastLng, northLat]`) and integer `zoom`, returns an array of clusters and points as [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) objects. -->
4863

4964
#### `getTile(z, x, y)`
@@ -63,9 +78,15 @@ Returns all the points of a cluster (given its `cluster_id`), with pagination su
6378

6479
Returns the zoom on which the cluster expands into several children (useful for "click to zoom" feature) given the cluster's `cluster_id`.
6580

81+
#### `destroy()`
82+
83+
Destroys the c++ cluster and frees its memory
84+
6685
## TO-DOs
86+
6787
- Proper input and return types for methods
68-
- Implement ```getClusters(bbox, zoom)```
88+
- Implement `getClusters(bbox, zoom)`
89+
- Find a better implementation for `destroy()`
6990
- Parse and return additional Point properties added by users
7091
- Map/reduce options
7192

cpp/clusterer.cpp

+17-5
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ map<string, mapbox::supercluster::Supercluster *> clusterMap = map<string, mapbo
1212
void cluster_init(jsi::Runtime &rt, jsi::Value const &nVal, jsi::Value const &fVal, jsi::Value const &oVal)
1313
{
1414
auto name = nVal.asString(rt).utf8(rt);
15-
auto features = cluster_parseJSIFeatures(rt, fVal);
16-
auto options = cluster_parseJSIOptions(rt, oVal);
15+
auto features = parseJSIFeatures(rt, fVal);
16+
auto options = parseJSIOptions(rt, oVal);
1717
auto *cluster = new mapbox::supercluster::Supercluster(features, options);
1818
clusterMap[name] = cluster;
1919
}
@@ -70,7 +70,19 @@ int cluster_getClusterExpansionZoom(string name, int cluster_id)
7070
return (int)cluster->getClusterExpansionZoom(cluster_id);
7171
}
7272

73-
mapbox::feature::feature_collection<double> cluster_parseJSIFeatures(jsi::Runtime &rt, jsi::Value const &value)
73+
74+
void cluster_destroyCluster(string name){
75+
mapbox::supercluster::Supercluster *cluster = clusterMap[name];
76+
delete cluster;
77+
clusterMap.erase(name);
78+
}
79+
80+
/*
81+
82+
Helper functions
83+
84+
*/
85+
mapbox::feature::feature_collection<double> parseJSIFeatures(jsi::Runtime &rt, jsi::Value const &value)
7486
{
7587
mapbox::feature::feature_collection<double> features;
7688
if (value.asObject(rt).isArray(rt))
@@ -89,7 +101,7 @@ mapbox::feature::feature_collection<double> cluster_parseJSIFeatures(jsi::Runtim
89101
return features;
90102
};
91103

92-
mapbox::supercluster::Options cluster_parseJSIOptions(jsi::Runtime &rt, jsi::Value const &value)
104+
mapbox::supercluster::Options parseJSIOptions(jsi::Runtime &rt, jsi::Value const &value)
93105
{
94106
mapbox::supercluster::Options options;
95107
if (value.isObject())
@@ -153,7 +165,7 @@ mapbox::supercluster::Options cluster_parseJSIOptions(jsi::Runtime &rt, jsi::Val
153165
{
154166
jsi::Value generateId = obj.getProperty(rt, "generateId");
155167
if (generateId.isBool())
156-
{
168+
{
157169
options.generateId = generateId.getBool();
158170
}
159171
else

cpp/clusterer.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ jsi::Array cluster_getLeaves(jsi::Runtime &rt, string name, int cluster_id, int
1919

2020
int cluster_getClusterExpansionZoom(string name, int cluster_id);
2121

22-
mapbox::supercluster::Options cluster_parseJSIOptions(jsi::Runtime &rt, jsi::Value const &value);
22+
void cluster_destroyCluster(string name);
23+
24+
mapbox::supercluster::Options parseJSIOptions(jsi::Runtime &rt, jsi::Value const &value);
2325

2426
mapbox::feature::feature<double> parseJSIFeature(jsi::Runtime &rt, jsi::Value const &value);
2527

26-
mapbox::feature::feature_collection<double> cluster_parseJSIFeatures(jsi::Runtime &rt, jsi::Value const &value);
28+
mapbox::feature::feature_collection<double> parseJSIFeatures(jsi::Runtime &rt, jsi::Value const &value);
2729

2830
jsi::Object tileToJSIObject(jsi::Runtime &rt, mapbox::feature::feature<double> &f, bool geometryAsInt);
2931

cpp/react-native-clusterer.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace clusterer
4343

4444
return cluster_getTile(rt, args[0].asString(rt).utf8(rt), (int)args[1].asNumber(), (int)args[2].asNumber(), (int)args[3].asNumber()); });
4545

46-
auto getChildren = jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "getTile"), 2, [](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
46+
auto getChildren = jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "getChildren"), 2, [](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
4747
{
4848
if (count != 2)
4949
{
@@ -74,7 +74,7 @@ namespace clusterer
7474

7575
return cluster_getLeaves(rt, args[0].asString(rt).utf8(rt), (int)args[1].asNumber(), (int)args[2].asNumber(), (int)args[3].asNumber()); });
7676

77-
auto getClusterExpansionZoom = jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "getLeaves"), 2, [](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
77+
auto getClusterExpansionZoom = jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "getClusterExpansionZoom"), 2, [](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
7878
{
7979
if (count != 2)
8080
{
@@ -89,12 +89,18 @@ namespace clusterer
8989

9090
return cluster_getClusterExpansionZoom(args[0].asString(rt).utf8(rt), (int)args[1].asNumber()); });
9191

92+
auto destroyCluster = jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "destroyCluster"), 1, [](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
93+
{
94+
cluster_destroyCluster(args[0].asString(rt).utf8(rt));
95+
return jsi::Value() });
96+
9297
jsi::Object module = jsi::Object(jsiRuntime);
9398
module.setProperty(jsiRuntime, "init", move(init));
9499
module.setProperty(jsiRuntime, "getTile", move(getTile));
95100
module.setProperty(jsiRuntime, "getChildren", move(getChildren));
96101
module.setProperty(jsiRuntime, "getLeaves", move(getLeaves));
97102
module.setProperty(jsiRuntime, "getClusterExpansionZoom", move(getClusterExpansionZoom));
103+
module.setProperty(jsiRuntime, "destroyCluster", move(destroyCluster));
98104

99105
jsiRuntime.global().setProperty(jsiRuntime, "clustererModule", move(module));
100106
}

example/src/superclustercpp.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export default function SuperclusterCPP() {
1717
const tileRes = supercluster.getTile(0, 0, 0);
1818
const getTileE = PerformanceNow();
1919

20+
supercluster.destroy();
21+
2022
setPoints(JSON.stringify(tileRes));
2123
setTime([timeDelta(initS, initE),timeDelta(getTileS, getTileE)])
2224
}

src/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,7 @@ export default class Clusterer {
3939
return module.getClusterExpansionZoom(this.id, clusterId);
4040
}
4141

42+
destroy(): void {
43+
module.destroyCluster(this.id);
44+
}
4245
}

0 commit comments

Comments
 (0)