diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-23 16:05:38 -1000 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2012-11-23 19:33:39 -0800 |
commit | a9786564c23fbf032f47096f543699c8c402785b (patch) | |
tree | 551231e54e017c9e83fd44da59edbe4c94dfa716 | |
parent | 10ce60e2120419282ff7694e8deda60e94832aa1 (diff) | |
download | subsurface-a9786564c23fbf032f47096f543699c8c402785b.tar.gz |
Allocate dive samples separately from 'struct dive'
We used to avoid some extra allocations by just allocating the dive
samples as part of the 'struct dive' allocation itself, but that ends up
complicating things, and will make it impossible to have multiple
different sets of samples (for multiple dive computers).
So stop doing it. Just allocate the dive samples array separately.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | dive.c | 52 | ||||
-rw-r--r-- | dive.h | 9 | ||||
-rw-r--r-- | divelist.c | 1 | ||||
-rw-r--r-- | file.c | 2 | ||||
-rw-r--r-- | libdivecomputer.c | 13 | ||||
-rw-r--r-- | parse-xml.c | 28 | ||||
-rw-r--r-- | uemis.c | 6 |
7 files changed, 45 insertions, 66 deletions
@@ -145,36 +145,30 @@ double get_weight_units(unsigned int grams, int *frac, const char **units) struct dive *alloc_dive(void) { - const int initial_samples = 5; - unsigned int size; struct dive *dive; - size = dive_size(initial_samples); - dive = malloc(size); + dive = malloc(sizeof(*dive)); if (!dive) exit(1); - memset(dive, 0, size); - dive->alloc_samples = initial_samples; + memset(dive, 0, sizeof(*dive)); return dive; } -struct sample *prepare_sample(struct dive **divep) +struct sample *prepare_sample(struct dive *dive) { - struct dive *dive = *divep; if (dive) { int nr = dive->samples; int alloc_samples = dive->alloc_samples; struct sample *sample; if (nr >= alloc_samples) { - unsigned int size; + struct sample *newsamples; alloc_samples = (alloc_samples * 3)/2 + 10; - size = dive_size(alloc_samples); - dive = realloc(dive, size); - if (!dive) + newsamples = realloc(dive->sample, alloc_samples * sizeof(struct sample)); + if (!newsamples) return NULL; dive->alloc_samples = alloc_samples; - *divep = dive; + dive->sample = newsamples; } sample = dive->sample + nr; memset(sample, 0, sizeof(*sample)); @@ -593,16 +587,16 @@ struct dive *fixup_dive(struct dive *dive) #define MERGE_MAX_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : MAX(a->n, b->n) #define MERGE_MIN_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : (a->n)?(b->n)?MIN(a->n, b->n):(a->n):(b->n) -static struct dive *add_sample(struct sample *sample, int time, struct dive *dive) +static struct sample *add_sample(struct sample *sample, int time, struct dive *dive) { - struct sample *p = prepare_sample(&dive); + struct sample *p = prepare_sample(dive); - if (!p) - return NULL; - *p = *sample; - p->time.seconds = time; - finish_sample(dive); - return dive; + if (p) { + *p = *sample; + p->time.seconds = time; + finish_sample(dive); + } + return p; } /* @@ -613,18 +607,18 @@ static struct dive *add_sample(struct sample *sample, int time, struct dive *div * that the time in between the dives is at the surface, not some "last * sample that happened to be at a depth of 1.2m". */ -static struct dive *merge_one_sample(struct sample *sample, int time, struct dive *dive) +static void merge_one_sample(struct sample *sample, int time, struct dive *dive) { int last = dive->samples-1; if (last >= 0) { static struct sample surface; int last_time = dive->sample[last].time.seconds; if (time > last_time + 60) { - dive = add_sample(&surface, last_time+20, dive); - dive = add_sample(&surface, time - 20, dive); + add_sample(&surface, last_time+20, dive); + add_sample(&surface, time - 20, dive); } } - return add_sample(sample, time, dive); + add_sample(sample, time, dive); } @@ -670,7 +664,7 @@ static struct dive *merge_samples(struct dive *res, struct dive *a, struct dive /* Only samples from a? */ if (bt < 0) { add_sample_a: - res = merge_one_sample(as, at, res); + merge_one_sample(as, at, res); as++; asamples--; continue; @@ -679,7 +673,7 @@ add_sample_a: /* Only samples from b? */ if (at < 0) { add_sample_b: - res = merge_one_sample(bs, bt, res); + merge_one_sample(bs, bt, res); bs++; bsamples--; continue; @@ -701,7 +695,7 @@ add_sample_b: if (as->cylinderindex) sample.cylinderindex = as->cylinderindex; - res = merge_one_sample(&sample, at, res); + merge_one_sample(&sample, at, res); as++; bs++; @@ -717,7 +711,7 @@ static struct dive *copy_samples(struct dive *res, struct dive *src) while (samples) { if (!res) return NULL; - res = add_sample(s, s->time.seconds, res); + add_sample(s, s->time.seconds, res); s++; samples--; } @@ -281,7 +281,7 @@ struct dive { int sac, otu; struct event *events; int samples, alloc_samples; - struct sample sample[]; + struct sample *sample; }; /* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m @@ -415,11 +415,6 @@ extern void show_yearly_stats(void); extern void update_dive(struct dive *new_dive); extern void save_dives(const char *filename); -static inline unsigned int dive_size(int samples) -{ - return sizeof(struct dive) + samples*sizeof(struct sample); -} - extern timestamp_t utc_mktime(struct tm *tm); extern void utc_mkdate(timestamp_t, struct tm *tm); @@ -427,7 +422,7 @@ extern struct dive *alloc_dive(void); extern void record_dive(struct dive *dive); extern void delete_dive(struct dive *dive); -extern struct sample *prepare_sample(struct dive **divep); +extern struct sample *prepare_sample(struct dive *dive); extern void finish_sample(struct dive *dive); extern void report_dives(gboolean imported, gboolean prefer_imported); diff --git a/divelist.c b/divelist.c index 37efed67a..13eda68b5 100644 --- a/divelist.c +++ b/divelist.c @@ -1931,6 +1931,7 @@ void delete_single_dive(int idx) dive_table.nr--; if (dive->selected) amount_selected--; + free(dive->sample); free(dive); } @@ -204,7 +204,7 @@ static int try_to_open_csv(const char *filename, struct memblock *mem, enum csv_ if (errno) break; - sample = prepare_sample(&dive); + sample = prepare_sample(dive); sample->time.seconds = time; add_sample_data(sample, type, val); finish_sample(dive); diff --git a/libdivecomputer.c b/libdivecomputer.c index d4ffcc174..6ced23a48 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -115,8 +115,7 @@ void sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) { int i; - struct dive **divep = userdata; - struct dive *dive = *divep; + struct dive *dive = userdata; struct sample *sample; /* @@ -127,9 +126,9 @@ sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) switch (type) { case DC_SAMPLE_TIME: - sample = prepare_sample(divep); + sample = prepare_sample(dive); sample->time.seconds = value.time; - finish_sample(*divep); + finish_sample(dive); break; case DC_SAMPLE_DEPTH: sample->depth.mm = value.depth * 1000 + 0.5; @@ -177,10 +176,10 @@ static void dev_info(device_data_t *devdata, const char *fmt, ...) static int import_dive_number = 0; -static int parse_samples(device_data_t *devdata, struct dive **divep, dc_parser_t *parser) +static int parse_samples(device_data_t *devdata, struct dive *dive, dc_parser_t *parser) { // Parse the sample data. - return dc_parser_samples_foreach(parser, sample_cb, divep); + return dc_parser_samples_foreach(parser, sample_cb, dive); } /* @@ -303,7 +302,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, } // Initialize the sample data. - rc = parse_samples(devdata, &dive, parser); + rc = parse_samples(devdata, dive, parser); if (rc != DC_STATUS_SUCCESS) { dev_info(devdata, _("Error parsing the samples")); dc_parser_destroy(parser); diff --git a/parse-xml.c b/parse-xml.c index 04d39643b..2593ed399 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -773,10 +773,8 @@ static void divinglog_place(char *place, void *_location) country = NULL; } -static int divinglog_dive_match(struct dive **divep, const char *name, int len, char *buf) +static int divinglog_dive_match(struct dive *dive, const char *name, int len, char *buf) { - struct dive *dive = *divep; - return MATCH(".divedate", divedate, &dive->when) || MATCH(".entrytime", divetime, &dive->when) || MATCH(".depth", depth, &dive->maxdepth) || @@ -955,10 +953,8 @@ static void uemis_percent(char *buffer, void *_cylinder) percent(buffer, &cur_dive->cylinder[index].gasmix.o2); } -static int uemis_dive_match(struct dive **divep, const char *name, int len, char *buf) +static int uemis_dive_match(struct dive *dive, const char *name, int len, char *buf) { - struct dive *dive = *divep; - return MATCH(".units.length", uemis_length_unit, &input_units) || MATCH(".units.volume", uemis_volume_unit, &input_units) || MATCH(".units.pressure", uemis_pressure_unit, &input_units) || @@ -986,7 +982,7 @@ static int uemis_dive_match(struct dive **divep, const char *name, int len, char MATCH(".nitrox_3.travel_tank.oxygen", uemis_percent, dive->cylinder + 6) || MATCH(".dive.val.float", uemis_duration, &dive->duration) || MATCH(".dive.val.ts", uemis_ts, &dive->when) || - MATCH(".dive.val.bin", uemis_parse_divelog_binary, divep) || + MATCH(".dive.val.bin", uemis_parse_divelog_binary, dive) || 0; } @@ -1034,10 +1030,8 @@ success: free(buffer); } -static int uddf_dive_match(struct dive **divep, const char *name, int len, char *buf) +static int uddf_dive_match(struct dive *dive, const char *name, int len, char *buf) { - struct dive *dive = *divep; - return MATCH(".datetime", uddf_datetime, &dive->when) || MATCH(".diveduration", duration, &dive->duration) || MATCH(".greatestdepth", depth, &dive->maxdepth) || @@ -1055,7 +1049,7 @@ static void gps_location(char *buffer, void *_dive) } /* We're in the top-level dive xml. Try to convert whatever value to a dive value */ -static void try_to_fill_dive(struct dive **divep, const char *name, char *buf) +static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) { int len = strlen(name); @@ -1063,17 +1057,17 @@ static void try_to_fill_dive(struct dive **divep, const char *name, char *buf) switch (import_source) { case UEMIS: - if (uemis_dive_match(divep, name, len, buf)) + if (uemis_dive_match(dive, name, len, buf)) return; break; case DIVINGLOG: - if (divinglog_dive_match(divep, name, len, buf)) + if (divinglog_dive_match(dive, name, len, buf)) return; break; case UDDF: - if (uddf_dive_match(divep, name, len, buf)) + if (uddf_dive_match(dive, name, len, buf)) return; break; @@ -1081,8 +1075,6 @@ static void try_to_fill_dive(struct dive **divep, const char *name, char *buf) break; } - struct dive *dive = *divep; - if (MATCH(".number", get_index, &dive->number)) return; if (MATCH(".tripflag", get_tripflag, &dive->tripflag)) @@ -1288,7 +1280,7 @@ static void ws_end(void) static void sample_start(void) { - cur_sample = prepare_sample(&cur_dive); + cur_sample = prepare_sample(cur_dive); } static void sample_end(void) @@ -1317,7 +1309,7 @@ static void entry(const char *name, int size, const char *raw) return; } if (cur_dive) { - try_to_fill_dive(&cur_dive, name, buf); + try_to_fill_dive(cur_dive, name, buf); return; } if (cur_trip) { @@ -185,8 +185,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap) { uint8_t *data; struct sample *sample; uemis_sample_t *u_sample; - struct dive **divep = datap; - struct dive *dive = *divep; + struct dive *dive = datap; int template, gasoffset; in_deco = FALSE; @@ -236,8 +235,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap) { * duration in the header is a) in minutes and b) up to 3 minutes short */ if (u_sample->dive_time > dive->duration.seconds + 180) break; - sample = prepare_sample(divep); - dive = *divep; /* prepare_sample might realloc the dive */ + sample = prepare_sample(dive); sample->time.seconds = u_sample->dive_time; sample->depth.mm = rel_mbar_to_depth(u_sample->water_pressure, dive); sample->temperature.mkelvin = (u_sample->dive_temperature * 100) + 273150; |