[PATCH 1/2] Allocate dive samples separately from 'struct dive'

Linus Torvalds torvalds at linux-foundation.org
Fri Nov 23 19:01:51 PST 2012


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Fri, 23 Nov 2012 16:05:38 -1000
Subject: [PATCH 1/2] 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 at linux-foundation.org>
---

This is just preparatory, and fairly trivial. It simplifies some code 
because now "struct dive *" doesn't change when you add samples, since you 
don't have to re-allocate the dive (just the sample array). That explains 
why this removes more lines of code than it adds, even though it's pretty 
much just a mechanical conversion.

 dive.c            | 52 +++++++++++++++++++++++-----------------------------
 dive.h            |  9 ++-------
 divelist.c        |  1 +
 file.c            |  2 +-
 libdivecomputer.c | 13 ++++++-------
 parse-xml.c       | 28 ++++++++++------------------
 uemis.c           |  6 ++----
 7 files changed, 45 insertions(+), 66 deletions(-)

diff --git a/dive.c b/dive.c
index ae9ecde0085a..be7d890f4c8b 100644
--- a/dive.c
+++ b/dive.c
@@ -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--;
 	}
diff --git a/dive.h b/dive.h
index 7131b3eaf488..dbcd38090c43 100644
--- a/dive.h
+++ b/dive.h
@@ -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 59db7c208609..5c704b98a73c 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);
 }
 
diff --git a/file.c b/file.c
index db72b5f668de..d675d8dc6e63 100644
--- a/file.c
+++ b/file.c
@@ -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 d4ffcc174c69..6ced23a481ac 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 15138f43e8b2..6b8afa1f3aa5 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -772,10 +772,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) ||
@@ -954,10 +952,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) ||
@@ -985,7 +981,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;
 }
 
@@ -1033,10 +1029,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) ||
@@ -1054,7 +1048,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);
 
@@ -1062,17 +1056,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;
 
@@ -1080,8 +1074,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))
@@ -1286,7 +1278,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)
@@ -1315,7 +1307,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) {
diff --git a/uemis.c b/uemis.c
index 646c37d9aa78..d8bec845d208 100644
--- a/uemis.c
+++ b/uemis.c
@@ -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;
-- 
1.8.0



More information about the subsurface mailing list