Use weak pointers for container and parser to avoid reference loops

This commit is contained in:
Eric Fischer 2018-06-06 17:47:20 -07:00
parent 72cf2c7238
commit 98e2633b4a
13 changed files with 100 additions and 90 deletions

View File

@ -173,7 +173,7 @@ sqlite3 *dirmeta2tmp(const char *fname) {
exit(EXIT_FAILURE);
}
json_pull *jp = json_begin_file(f);
std::shared_ptr<json_pull> jp = json_begin_file(f);
std::shared_ptr<json_object> o = json_read_tree(jp);
if (o->type != JSON_HASH) {

View File

@ -298,7 +298,7 @@ std::shared_ptr<json_object> read_filter(const char *fname) {
exit(EXIT_FAILURE);
}
json_pull *jp = json_begin_file(fp);
std::shared_ptr<json_pull> jp = json_begin_file(fp);
std::shared_ptr<json_object> filter = json_read_tree(jp);
if (filter == NULL) {
fprintf(stderr, "%s: %s\n", fname, jp->error.c_str());
@ -311,7 +311,7 @@ std::shared_ptr<json_object> read_filter(const char *fname) {
}
std::shared_ptr<json_object> parse_filter(const char *s) {
json_pull *jp = json_begin_string(s);
std::shared_ptr<json_pull> jp = json_begin_string(s);
std::shared_ptr<json_object> filter = json_read_tree(jp);
if (filter == NULL) {
fprintf(stderr, "Could not parse filter %s\n", s);

View File

@ -390,7 +390,7 @@ void readFeature(protozero::pbf_reader &pbf, size_t dim, double e, std::vector<s
auto tip = other.find("tippecanoe");
if (tip != other.end()) {
json_pull *jp = json_begin_string(tip->second.s.c_str());
std::shared_ptr<json_pull> jp = json_begin_string(tip->second.s.c_str());
std::shared_ptr<json_object> o = json_read_tree(jp);
if (o != NULL) {

View File

@ -232,7 +232,7 @@ void check_crs(std::shared_ptr<json_object> j, const char *reading) {
}
}
void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std::string layername) {
void parse_json(struct serialization_state *sst, std::shared_ptr<json_pull> jp, int layer, std::string layername) {
long long found_hashes = 0;
long long found_features = 0;
long long found_geometries = 0;
@ -275,17 +275,20 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std::
}
if (is_geometry) {
if (j->parent != NULL) {
if (j->parent->type == JSON_ARRAY && j->parent->parent != NULL) {
if (j->parent->parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometries = json_hash_get(j->parent->parent, "geometries");
std::shared_ptr<json_object> parent = j->parent.lock();
if (parent.use_count() != 0) {
if (parent->type == JSON_ARRAY) {
std::shared_ptr<json_object> parent_parent = parent->parent.lock();
if (parent_parent.use_count() != 0 && parent_parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometries = json_hash_get(parent_parent, "geometries");
if (geometries != NULL) {
// Parent of Parent must be a GeometryCollection
is_geometry = 0;
}
}
} else if (j->parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometry = json_hash_get(j->parent, "geometry");
} else if (parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometry = json_hash_get(parent, "geometry");
if (geometry != NULL) {
// Parent must be a Feature
is_geometry = 0;
@ -369,7 +372,7 @@ struct jsonmap {
unsigned long long end;
};
ssize_t json_map_read(struct json_pull *jp, char *buffer, size_t n) {
ssize_t json_map_read(std::shared_ptr<json_pull> jp, char *buffer, size_t n) {
struct jsonmap *jm = (struct jsonmap *) jp->source;
if (jm->off + n >= jm->end) {
@ -382,7 +385,7 @@ ssize_t json_map_read(struct json_pull *jp, char *buffer, size_t n) {
return n;
}
struct json_pull *json_begin_map(char *map, long long len) {
std::shared_ptr<json_pull> json_begin_map(char *map, long long len) {
struct jsonmap *jm = new jsonmap;
if (jm == NULL) {
perror("Out of memory");
@ -396,7 +399,7 @@ struct json_pull *json_begin_map(char *map, long long len) {
return json_begin(json_map_read, jm);
}
void json_end_map(struct json_pull *jp) {
void json_end_map(std::shared_ptr<json_pull> jp) {
delete (struct jsonmap *) jp->source;
json_end(jp);
}

View File

@ -10,21 +10,21 @@
#include "serial.hpp"
struct parse_json_args {
json_pull *jp;
std::shared_ptr<json_pull> jp;
int layer;
std::string *layername;
struct serialization_state *sst;
parse_json_args(json_pull *jp1, int layer1, std::string *layername1, struct serialization_state *sst1)
parse_json_args(std::shared_ptr<json_pull> jp1, int layer1, std::string *layername1, struct serialization_state *sst1)
: jp(jp1), layer(layer1), layername(layername1), sst(sst1) {
}
};
struct json_pull *json_begin_map(char *map, long long len);
void json_end_map(struct json_pull *jp);
std::shared_ptr<json_pull> json_begin_map(char *map, long long len);
void json_end_map(std::shared_ptr<json_pull> jp);
void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std::string layername);
void parse_json(struct serialization_state *sst, std::shared_ptr<json_pull> jp, int layer, std::string layername);
void *run_parse_json(void *v);
#endif

View File

@ -8,8 +8,8 @@
#define BUFFER 10000
json_pull *json_begin(ssize_t (*read)(struct json_pull *, char *buffer, size_t n), void *source) {
json_pull *j = new json_pull;
std::shared_ptr<json_pull> json_begin(ssize_t (*read)(std::shared_ptr<json_pull> , char *buffer, size_t n), void *source) {
std::shared_ptr<json_pull> j = std::make_shared<json_pull>();
if (j == NULL) {
perror("Out of memory");
exit(EXIT_FAILURE);
@ -30,7 +30,7 @@ json_pull *json_begin(ssize_t (*read)(struct json_pull *, char *buffer, size_t n
return j;
}
static inline int peek(json_pull *j) {
static inline int peek(std::shared_ptr<json_pull> j) {
if (j->buffer_head < j->buffer_tail) {
return (unsigned char) j->buffer[j->buffer_head];
} else {
@ -43,7 +43,7 @@ static inline int peek(json_pull *j) {
}
}
static inline int next(json_pull *j) {
static inline int next(std::shared_ptr<json_pull> j) {
if (j->buffer_head < j->buffer_tail) {
return (unsigned char) j->buffer[j->buffer_head++];
} else {
@ -56,15 +56,15 @@ static inline int next(json_pull *j) {
}
}
static ssize_t read_file(json_pull *j, char *buffer, size_t n) {
static ssize_t read_file(std::shared_ptr<json_pull> j, char *buffer, size_t n) {
return fread(buffer, 1, n, (FILE *) j->source);
}
json_pull *json_begin_file(FILE *f) {
std::shared_ptr<json_pull> json_begin_file(FILE *f) {
return json_begin(read_file, f);
}
static ssize_t read_string(json_pull *j, char *buffer, size_t n) {
static ssize_t read_string(std::shared_ptr<json_pull> j, char *buffer, size_t n) {
const char *cp = (const char *) j->source;
size_t out = 0;
@ -77,16 +77,15 @@ static ssize_t read_string(json_pull *j, char *buffer, size_t n) {
return out;
}
json_pull *json_begin_string(const char *s) {
std::shared_ptr<json_pull> json_begin_string(const char *s) {
return json_begin(read_string, (void *) s);
}
void json_end(json_pull *p) {
void json_end(std::shared_ptr<json_pull> p) {
json_free(p->root);
delete p;
}
static inline int read_wrap(json_pull *j) {
static inline int read_wrap(std::shared_ptr<json_pull> j) {
int c = next(j);
if (c == '\n') {
@ -96,7 +95,7 @@ static inline int read_wrap(json_pull *j) {
return c;
}
static std::shared_ptr<json_object> fabricate_object(json_pull *jp, std::shared_ptr<json_object> parent, json_type type) {
static std::shared_ptr<json_object> fabricate_object(std::shared_ptr<json_pull> jp, std::shared_ptr<json_object> parent, json_type type) {
std::shared_ptr<json_object> o = std::make_shared<json_object>();
if (o == NULL) {
perror("Out of memory");
@ -108,7 +107,7 @@ static std::shared_ptr<json_object> fabricate_object(json_pull *jp, std::shared_
return o;
}
static std::shared_ptr<json_object> add_object(json_pull *j, json_type type) {
static std::shared_ptr<json_object> add_object(std::shared_ptr<json_pull> j, json_type type) {
std::shared_ptr<json_object> c = j->container;
std::shared_ptr<json_object> o = fabricate_object(j, c, type);
@ -151,7 +150,7 @@ static std::shared_ptr<json_object> add_object(json_pull *j, json_type type) {
}
std::shared_ptr<json_object> json_hash_get(std::shared_ptr<json_object> o, std::string const &s) {
if (o == NULL || o->type != JSON_HASH) {
if (o == NULL || o.use_count() == 0 || o->type != JSON_HASH) {
return NULL;
}
@ -167,7 +166,7 @@ std::shared_ptr<json_object> json_hash_get(std::shared_ptr<json_object> o, std::
return NULL;
}
std::shared_ptr<json_object> json_read_separators(json_pull *j, json_separator_callback cb, void *state) {
std::shared_ptr<json_object> json_read_separators(std::shared_ptr<json_pull> j, json_separator_callback cb, void *state) {
int c;
// In case there is an error at the top level
@ -225,7 +224,7 @@ again:
goto again;
} else if (c == ']') {
if (j->container == NULL) {
if (j->container.use_count() == 0) {
j->error = "Found ] at top level";
return NULL;
}
@ -243,7 +242,7 @@ again:
}
std::shared_ptr<json_object> ret = j->container;
j->container = ret->parent;
j->container = ret->parent.lock();
return ret;
}
@ -263,7 +262,7 @@ again:
goto again;
} else if (c == '}') {
if (j->container == NULL) {
if (j->container.use_count() == 0) {
j->error = "Found } at top level";
return NULL;
}
@ -281,7 +280,7 @@ again:
}
std::shared_ptr<json_object> ret = j->container;
j->container = ret->parent;
j->container = ret->parent.lock();
return ret;
}
@ -586,15 +585,16 @@ again:
return NULL;
}
std::shared_ptr<json_object> json_read(json_pull *j) {
std::shared_ptr<json_object> json_read(std::shared_ptr<json_pull> j) {
return json_read_separators(j, NULL, NULL);
}
std::shared_ptr<json_object> json_read_tree(json_pull *p) {
std::shared_ptr<json_object> json_read_tree(std::shared_ptr<json_pull> p) {
std::shared_ptr<json_object> j;
while ((j = json_read(p)) != NULL) {
if (j->parent == NULL) {
std::shared_ptr<json_object> parent = j->parent.lock();
if (parent.use_count() == 0) {
return j;
}
}
@ -651,59 +651,62 @@ static void json_disconnect_parser(std::shared_ptr<json_object> o) {
}
}
o->parser = NULL;
o->parser = std::weak_ptr<json_pull>();
}
void json_disconnect(std::shared_ptr<json_object> o) {
// Expunge references to this as an array element
// or a hash key or value.
if (o->parent != NULL) {
if (o->parent->type == JSON_ARRAY) {
std::shared_ptr<json_object> parent = o->parent.lock();
std::shared_ptr<json_pull> parser = o->parser.lock();
if (parent.use_count() != 0) {
if (parent->type == JSON_ARRAY) {
size_t i;
for (i = 0; i < o->parent->array.size(); i++) {
if (o->parent->array[i] == o) {
for (i = 0; i < parent->array.size(); i++) {
if (parent->array[i] == o) {
break;
}
}
if (i < o->parent->array.size()) {
o->parent->array.erase(o->parent->array.begin() + i);
if (i < parent->array.size()) {
parent->array.erase(parent->array.begin() + i);
}
}
if (o->parent->type == JSON_HASH) {
if (parent->type == JSON_HASH) {
size_t i;
for (i = 0; i < o->parent->keys.size(); i++) {
if (o->parent->keys[i] == o) {
o->parent->keys[i] = fabricate_object(o->parser, o->parent, JSON_NULL);
for (i = 0; i < parent->keys.size(); i++) {
if (parent->keys[i] == o) {
parent->keys[i] = fabricate_object(parser, parent, JSON_NULL);
break;
}
if (o->parent->values[i] == o) {
o->parent->values[i] = fabricate_object(o->parser, o->parent, JSON_NULL);
if (parent->values[i] == o) {
parent->values[i] = fabricate_object(parser, parent, JSON_NULL);
break;
}
}
if (i < o->parent->keys.size()) {
if (o->parent->keys[i] != NULL && o->parent->keys[i]->type == JSON_NULL) {
if (o->parent->values[i] != NULL && o->parent->values[i]->type == JSON_NULL) {
o->parent->keys.erase(o->parent->keys.begin() + i);
o->parent->values.erase(o->parent->values.begin() + i);
if (i < parent->keys.size()) {
if (parent->keys[i] != NULL && parent->keys[i]->type == JSON_NULL) {
if (parent->values[i] != NULL && parent->values[i]->type == JSON_NULL) {
parent->keys.erase(parent->keys.begin() + i);
parent->values.erase(parent->values.begin() + i);
}
}
}
}
}
if (o->parser != NULL && o->parser->root == o) {
o->parser->root = NULL;
if (parser.use_count() != 0 && parser->root == o) {
parser->root = NULL;
}
json_disconnect_parser(o);
o->parent = NULL;
o->parent = std::weak_ptr<json_object>();
}
static void json_print_one(std::string &val, std::shared_ptr<json_object> o) {

View File

@ -26,11 +26,12 @@ typedef enum json_type {
} json_type;
struct json_object;
struct json_pull;
struct json_object {
json_type type;
std::shared_ptr<struct json_object> parent;
struct json_pull *parser;
std::weak_ptr<json_object> parent;
std::weak_ptr<json_pull> parser;
std::string string;
double number;
@ -46,7 +47,7 @@ typedef struct json_pull {
std::string error;
size_t line;
ssize_t (*read)(struct json_pull *, char *buf, size_t n);
ssize_t (*read)(std::shared_ptr<json_pull> jp, char *buf, size_t n);
void *source;
std::string buffer;
ssize_t buffer_tail;
@ -56,17 +57,17 @@ typedef struct json_pull {
std::shared_ptr<json_object> root;
} json_pull;
json_pull *json_begin_file(FILE *f);
json_pull *json_begin_string(const char *s);
std::shared_ptr<json_pull> json_begin_file(FILE *f);
std::shared_ptr<json_pull> json_begin_string(const char *s);
json_pull *json_begin(ssize_t (*read)(struct json_pull *, char *buffer, size_t n), void *source);
void json_end(json_pull *p);
std::shared_ptr<json_pull> json_begin(ssize_t (*read)(std::shared_ptr<json_pull> jp, char *buffer, size_t n), void *source);
void json_end(std::shared_ptr<json_pull> p);
typedef void (*json_separator_callback)(json_type type, json_pull *j, void *state);
typedef void (*json_separator_callback)(json_type type, std::shared_ptr<json_pull> j, void *state);
std::shared_ptr<json_object> json_read_tree(json_pull *j);
std::shared_ptr<json_object> json_read(json_pull *j);
std::shared_ptr<json_object> json_read_separators(json_pull *j, json_separator_callback cb, void *state);
std::shared_ptr<json_object> json_read_tree(std::shared_ptr<json_pull> j);
std::shared_ptr<json_object> json_read(std::shared_ptr<json_pull> j);
std::shared_ptr<json_object> json_read_separators(std::shared_ptr<json_pull> j, json_separator_callback cb, void *state);
void json_free(std::shared_ptr<json_object> j);
void json_disconnect(std::shared_ptr<json_object> j);

View File

@ -340,7 +340,7 @@ void join_csv(std::shared_ptr<json_object> j) {
}
void process(FILE *fp, const char *fname) {
json_pull *jp = json_begin_file(fp);
std::shared_ptr<json_pull> jp = json_begin_file(fp);
while (1) {
std::shared_ptr<json_object> j = json_read(jp);
@ -373,17 +373,20 @@ void process(FILE *fp, const char *fname) {
type->string == "MultiPolygon") {
int is_geometry = 1;
if (j->parent != NULL) {
if (j->parent->type == JSON_ARRAY && j->parent->parent != NULL) {
if (j->parent->parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometries = json_hash_get(j->parent->parent, "geometries");
std::shared_ptr<json_object> parent = j->parent.lock();
if (parent.use_count() != 0) {
if (parent->type == JSON_ARRAY) {
std::shared_ptr<json_object> parent_parent = parent->parent.lock();
if (parent_parent.use_count() != 0 && parent_parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometries = json_hash_get(parent_parent, "geometries");
if (geometries != NULL) {
// Parent of Parent must be a GeometryCollection
is_geometry = 0;
}
}
} else if (j->parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometry = json_hash_get(j->parent, "geometry");
} else if (parent->type == JSON_HASH) {
std::shared_ptr<json_object> geometry = json_hash_get(parent, "geometry");
if (geometry != NULL) {
// Parent must be a Feature
is_geometry = 0;

View File

@ -478,7 +478,7 @@ void do_read_parallel(char *map, long long len, long long initial_offset, const
}
}
static ssize_t read_stream(json_pull *j, char *buffer, size_t n);
static ssize_t read_stream(std::shared_ptr<json_pull> j, char *buffer, size_t n);
struct STREAM {
FILE *fp = NULL;
@ -526,12 +526,12 @@ struct STREAM {
}
}
json_pull *json_begin() {
std::shared_ptr<json_pull> json_begin() {
return ::json_begin(read_stream, this);
}
};
static ssize_t read_stream(json_pull *j, char *buffer, size_t n) {
static ssize_t read_stream(std::shared_ptr<json_pull> j, char *buffer, size_t n) {
return ((STREAM *) j->source)->read(buffer, n);
}
@ -1640,7 +1640,7 @@ int read_input(std::vector<source> &sources, char *fname, int maxzoom, int minzo
// Plain serial reading
std::atomic<long long> layer_seq(overall_offset);
json_pull *jp = fp->json_begin();
std::shared_ptr<json_pull> jp = fp->json_begin();
struct serialization_state sst;
sst.fname = reading.c_str();
@ -2375,7 +2375,7 @@ void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, c
}
void parse_json_source(const char *arg, struct source &src) {
json_pull *jp = json_begin_string(arg);
std::shared_ptr<json_pull> jp = json_begin_string(arg);
std::shared_ptr<json_object> o = json_read_tree(jp);
if (o == NULL) {

View File

@ -92,7 +92,7 @@ std::vector<mvt_layer> parse_layers(int fd, int z, unsigned x, unsigned y, std::
perror("fdopen filter output");
exit(EXIT_FAILURE);
}
json_pull *jp = json_begin_file(f);
std::shared_ptr<json_pull> jp = json_begin_file(f);
while (1) {
std::shared_ptr<json_object> j = json_read(jp);
@ -295,7 +295,7 @@ std::vector<mvt_layer> parse_layers(int fd, int z, unsigned x, unsigned y, std::
}
// Reads from the prefilter
serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::vector<std::map<std::string, layermap_entry>> *layermaps, size_t tiling_seg, std::vector<std::vector<std::string>> *layer_unmaps, bool postfilter) {
serial_feature parse_feature(std::shared_ptr<json_pull> jp, int z, unsigned x, unsigned y, std::vector<std::map<std::string, layermap_entry>> *layermaps, size_t tiling_seg, std::vector<std::vector<std::string>> *layer_unmaps, bool postfilter) {
serial_feature sf;
while (1) {

View File

@ -1,3 +1,3 @@
std::vector<mvt_layer> filter_layers(const char *filter, std::vector<mvt_layer> &layer, unsigned z, unsigned x, unsigned y, std::vector<std::map<std::string, layermap_entry>> *layermaps, size_t tiling_seg, std::vector<std::vector<std::string>> *layer_unmaps, int extent);
void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, unsigned z, unsigned x, unsigned y);
serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::vector<std::map<std::string, layermap_entry>> *layermaps, size_t tiling_seg, std::vector<std::vector<std::string>> *layer_unmaps, bool filters);
serial_feature parse_feature(std::shared_ptr<json_pull> jp, int z, unsigned x, unsigned y, std::vector<std::map<std::string, layermap_entry>> *layermaps, size_t tiling_seg, std::vector<std::vector<std::string>> *layer_unmaps, bool filters);

View File

@ -793,7 +793,7 @@ void decode(struct reader *readers, std::map<std::string, layermap_entry> &layer
const unsigned char *s = sqlite3_column_text(r->stmt, 0);
if (s != NULL) {
json_pull *jp = json_begin_string((const char *) s);
std::shared_ptr<json_pull> jp = json_begin_string((const char *) s);
std::shared_ptr<json_object> o = json_read_tree(jp);
if (o != NULL && o->type == JSON_HASH) {

View File

@ -1741,7 +1741,7 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
pthread_t prefilter_writer;
run_prefilter_args rpa; // here so it stays in scope until joined
FILE *prefilter_read_fp = NULL;
json_pull *prefilter_jp = NULL;
std::shared_ptr<json_pull> prefilter_jp = NULL;
if (prefilter != NULL) {
setup_filter(prefilter, &prefilter_write, &prefilter_read, &prefilter_pid, z, tx, ty);