mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	Planner: don't return static data in fake_dc()
fake_dc() used to return a statically allocated dc with statically allocated samples. This is of course a questionable practice in the light of multi-threading / resource ownership. Once these problems were recognized, the parameter "alloc" was added. If set to true, the function would still return a statically allocated dc, but heap-allocated samples, which could then be copied in a different dc. All in all an ownership nightmare and a recipie for disaster. The returned static dc was only used as a pointer to the samples anyway. There are four callers of fake_dc() and they all have access to a dc-structure without samples. Therefore, change the semantics of fake_dc() to fill out the passed in dc. If the caller does not care about the samples, it can simply reset the sample number to zero after work. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
		
							parent
							
								
									450f0992a0
								
							
						
					
					
						commit
						920ff15f71
					
				
					 7 changed files with 39 additions and 40 deletions
				
			
		|  | @ -109,33 +109,29 @@ static void fill_samples_no_avg(struct sample *s, int max_d, int max_t, double s | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct divecomputer *fake_dc(struct divecomputer *dc, bool alloc) | ||||
| void fake_dc(struct divecomputer *dc) | ||||
| { | ||||
| 	static struct sample fake_samples[6]; | ||||
| 	static struct divecomputer fakedc; | ||||
| 	struct sample *fake = fake_samples; | ||||
| 	alloc_samples(dc, 6); | ||||
| 	struct sample *fake = dc->sample; | ||||
| 	int i; | ||||
| 
 | ||||
| 	fakedc = (*dc); | ||||
| 	if (alloc) | ||||
| 		fake = malloc(sizeof(fake_samples)); | ||||
| 
 | ||||
| 	fakedc.sample = fake; | ||||
| 	fakedc.samples = 6; | ||||
| 	dc->samples = 6; | ||||
| 
 | ||||
| 	/* The dive has no samples, so create a few fake ones */ | ||||
| 	int max_t = dc->duration.seconds; | ||||
| 	int max_d = dc->maxdepth.mm; | ||||
| 	int avg_d = dc->meandepth.mm; | ||||
| 
 | ||||
| 	memset(fake, 0, sizeof(fake_samples)); | ||||
| 	memset(fake, 0, 6 * sizeof(struct sample)); | ||||
| 	fake[5].time.seconds = max_t; | ||||
| 	for (i = 0; i < 6; i++) { | ||||
| 		fake_samples[i].bearing.degrees = -1; | ||||
| 		fake_samples[i].ndl.seconds = -1; | ||||
| 		fake[i].bearing.degrees = -1; | ||||
| 		fake[i].ndl.seconds = -1; | ||||
| 	} | ||||
| 	if (!max_t || !max_d) { | ||||
| 		dc->samples = 0; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!max_t || !max_d) | ||||
| 		return &fakedc; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We want to fake the profile so that the average | ||||
|  | @ -149,10 +145,10 @@ struct divecomputer *fake_dc(struct divecomputer *dc, bool alloc) | |||
| 		 * the user supplied data */ | ||||
| 		fill_samples_no_avg(fake, max_d, max_t, MAX(2.0 * max_d / max_t, 5000.0 / 60)); | ||||
| 		if (fake[3].time.seconds == 0) { // just a 4 point profile
 | ||||
| 			fakedc.samples = 4; | ||||
| 			dc->samples = 4; | ||||
| 			fake[3].time.seconds = max_t; | ||||
| 		} | ||||
| 		return &fakedc; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (avg_d < max_d / 10 || avg_d >= max_d) { | ||||
| 		avg_d = (max_d + 10000) / 3; | ||||
|  | @ -167,7 +163,7 @@ struct divecomputer *fake_dc(struct divecomputer *dc, bool alloc) | |||
| 	 * rate (5 meters per minute) and d_frac (1/3). | ||||
| 	 */ | ||||
| 	if (fill_samples(fake, max_d, avg_d, max_t, 5000.0 / 60, 0.33)) | ||||
| 		return &fakedc; | ||||
| 		return; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Ok, assume that didn't work because we cannot make the | ||||
|  | @ -175,7 +171,7 @@ struct divecomputer *fake_dc(struct divecomputer *dc, bool alloc) | |||
| 	 * followed by a much shallower region | ||||
| 	 */ | ||||
| 	if (fill_samples(fake, max_d, avg_d, max_t, 10000.0 / 60, 0.10)) | ||||
| 		return &fakedc; | ||||
| 		return; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Uhhuh. That didn't work. We'd need to find a good combination that | ||||
|  | @ -183,10 +179,9 @@ struct divecomputer *fake_dc(struct divecomputer *dc, bool alloc) | |||
| 	 * slopes. | ||||
| 	 */ | ||||
| 	if (fill_samples(fake, max_d, avg_d, max_t, 10000.0, 0.01)) | ||||
| 		return &fakedc; | ||||
| 		return; | ||||
| 
 | ||||
| 	/* Even that didn't work? Give up, there's something wrong */ | ||||
| 	return &fakedc; | ||||
| } | ||||
| 
 | ||||
| static void match_id(void *_dc, const char *model, uint32_t deviceid, | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| extern struct divecomputer *fake_dc(struct divecomputer *dc, bool alloc); | ||||
| extern void fake_dc(struct divecomputer *dc); | ||||
| extern void set_dc_deviceid(struct divecomputer *dc, unsigned int deviceid); | ||||
| extern void create_device_node(const char *model, uint32_t deviceid, const char *serial, const char *firmware, const char *nickname); | ||||
| extern void call_for_each_dc(void *f, void (*callback)(void *, const char *, uint32_t, | ||||
|  |  | |||
							
								
								
									
										28
									
								
								core/dive.c
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								core/dive.c
									
										
									
									
									
								
							|  | @ -714,22 +714,26 @@ void copy_samples(struct divecomputer *s, struct divecomputer *d) | |||
| 		memcpy(d->sample, s->sample, nr * sizeof(struct sample)); | ||||
| } | ||||
| 
 | ||||
| /* make room for num samples; if not enough space is available, the sample
 | ||||
|  * array is reallocated and the existing samples are copied. */ | ||||
| void alloc_samples(struct divecomputer *dc, int num) | ||||
| { | ||||
| 	if (num > dc->alloc_samples) { | ||||
| 		dc->alloc_samples = (dc->alloc_samples * 3) / 2 + 10; | ||||
| 		dc->sample = realloc(dc->sample, dc->alloc_samples * sizeof(struct sample)); | ||||
| 		if (!dc->sample) | ||||
| 			dc->samples = dc->alloc_samples = 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct sample *prepare_sample(struct divecomputer *dc) | ||||
| { | ||||
| 	if (dc) { | ||||
| 		int nr = dc->samples; | ||||
| 		int alloc_samples = dc->alloc_samples; | ||||
| 		struct sample *sample; | ||||
| 		if (nr >= alloc_samples) { | ||||
| 			struct sample *newsamples; | ||||
| 
 | ||||
| 			alloc_samples = (alloc_samples * 3) / 2 + 10; | ||||
| 			newsamples = realloc(dc->sample, alloc_samples * sizeof(struct sample)); | ||||
| 			if (!newsamples) | ||||
| 				return NULL; | ||||
| 			dc->alloc_samples = alloc_samples; | ||||
| 			dc->sample = newsamples; | ||||
| 		} | ||||
| 		alloc_samples(dc, nr + 1); | ||||
| 		if (!dc->sample) | ||||
| 			return NULL; | ||||
| 		sample = dc->sample + nr; | ||||
| 		memset(sample, 0, sizeof(*sample)); | ||||
| 
 | ||||
|  | @ -922,7 +926,7 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me | |||
| 		return; | ||||
| 	} | ||||
| 	if (!dc->samples) | ||||
| 		dc = fake_dc(dc, false); | ||||
| 		fake_dc(dc); | ||||
| 	struct event *ev = get_next_event(dc->events, "gaschange"); | ||||
| 	for (i = 0; i < dc->samples; i++) { | ||||
| 		struct sample *sample = dc->sample + i; | ||||
|  |  | |||
|  | @ -792,6 +792,7 @@ extern struct dive *clone_dive(struct dive *s); | |||
| 
 | ||||
| extern void clear_table(struct dive_table *table); | ||||
| 
 | ||||
| extern void alloc_samples(struct divecomputer *dc, int num); | ||||
| extern struct sample *prepare_sample(struct divecomputer *dc); | ||||
| extern void finish_sample(struct divecomputer *dc); | ||||
| extern void add_sample_pressure(struct sample *sample, int sensor, int mbar); | ||||
|  |  | |||
|  | @ -1089,9 +1089,9 @@ void QMLManager::commitChanges(QString diveId, QString date, QString location, Q | |||
| 			// so we have depth > 0, a manually added dive and no samples
 | ||||
| 			// let's create an actual profile so the desktop version can work it
 | ||||
| 			// first clear out the mean depth (or the fake_dc() function tries
 | ||||
| 			// to be too clever
 | ||||
| 			// to be too clever)
 | ||||
| 			d->meandepth.mm = d->dc.meandepth.mm = 0; | ||||
| 			d->dc = *fake_dc(&d->dc, true); | ||||
| 			fake_dc(&d->dc); | ||||
| 		} | ||||
| 		fixup_dive(d); | ||||
| 		DiveListModel::instance()->updateDive(modelIdx, d); | ||||
|  |  | |||
|  | @ -592,9 +592,8 @@ void ProfileWidget2::plotDive(struct dive *d, bool force) | |||
| 	// data that we have
 | ||||
| 	struct divecomputer *currentdc = select_dc(&displayed_dive); | ||||
| 	Q_ASSERT(currentdc); | ||||
| 	if (!currentdc || !currentdc->samples) { | ||||
| 		currentdc = fake_dc(currentdc, false); | ||||
| 	} | ||||
| 	if (!currentdc || !currentdc->samples) | ||||
| 		fake_dc(currentdc); | ||||
| 
 | ||||
| 	bool setpointflag = (currentdc->divemode == CCR) && prefs.pp_graphs.po2 && current_dive; | ||||
| 	bool sensorflag = setpointflag && prefs.show_ccr_sensors; | ||||
|  |  | |||
|  | @ -99,7 +99,7 @@ void DivePlannerPointsModel::loadFromDive(dive *d) | |||
| 	if (dc->samples) | ||||
| 		hasMarkedSamples = dc->sample[0].manually_entered; | ||||
| 	else | ||||
| 		dc = fake_dc(dc, true); | ||||
| 		fake_dc(dc); | ||||
| 
 | ||||
| 	// if this dive has more than 100 samples (so it is probably a logged dive),
 | ||||
| 	// average samples so we end up with a total of 100 samples.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue