changeset 15292:e2c62d70dfcf draft

(svn r19931) -Fix (r19914): Convert assertion in Backup<> destructor into DEBUG() output. It was triggered on exceptions, especially when aborting world generation.
author frosch <frosch@openttd.org>
date Sat, 05 Jun 2010 12:16:12 +0000
parents 90225375fccd
children bebb7d6af4a3
files src/ai/ai_core.cpp src/ai/ai_gui.cpp src/aircraft_cmd.cpp src/core/backup_type.hpp src/debug.h src/disaster_cmd.cpp src/economy.cpp src/industry_cmd.cpp src/industry_gui.cpp src/misc_cmd.cpp src/openttd.cpp src/rail_cmd.cpp src/roadveh_cmd.cpp src/saveload/afterload.cpp src/town_cmd.cpp src/vehicle.cpp src/water_cmd.cpp
diffstat 17 files changed, 62 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/ai_core.cpp
+++ b/src/ai/ai_core.cpp
@@ -69,7 +69,7 @@
 	assert(_settings_game.difficulty.competitor_speed <= 4);
 	if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
 
-	Backup<CompanyByte> cur_company(_current_company);
+	Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
 	const Company *c;
 	FOR_ALL_COMPANIES(c) {
 		if (c->is_ai) {
@@ -96,7 +96,7 @@
 {
 	if (_networking && !_network_server) return;
 
-	Backup<CompanyByte> cur_company(_current_company, company);
+	Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
 	Company *c = Company::Get(company);
 
 	delete c->ai_instance;
@@ -112,7 +112,7 @@
 {
 	if (_networking && !_network_server) return;
 
-	Backup<CompanyByte> cur_company(_current_company, company);
+	Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
 	Company::Get(company)->ai_instance->Suspend();
 
 	cur_company.Restore();
@@ -201,7 +201,7 @@
 	}
 
 	/* Queue the event */
-	Backup<CompanyByte> cur_company(_current_company, company);
+	Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
 	AIEventController::InsertEvent(event);
 	cur_company.Restore();
 
@@ -247,7 +247,7 @@
 		Company *c = Company::GetIfValid(company);
 		assert(c != NULL && c->ai_instance != NULL);
 
-		Backup<CompanyByte> cur_company(_current_company, company);
+		Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
 		c->ai_instance->Save();
 		cur_company.Restore();
 	} else {
@@ -261,7 +261,7 @@
 		Company *c = Company::GetIfValid(company);
 		assert(c != NULL && c->ai_instance != NULL);
 
-		Backup<CompanyByte> cur_company(_current_company, company);
+		Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
 		c->ai_instance->Load(version);
 		cur_company.Restore();
 	} else {
--- a/src/ai/ai_gui.cpp
+++ b/src/ai/ai_gui.cpp
@@ -820,7 +820,7 @@
 			DrawCompanyIcon(i, button->pos_x + button->current_x / 2 - 7 + offset, this->GetWidget<NWidgetBase>(AID_WIDGET_COMPANY_BUTTON_START + i)->pos_y + 2 + offset);
 		}
 
-		Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
+		Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 		cur_company.Restore();
 
@@ -875,7 +875,7 @@
 
 		switch (widget) {
 			case AID_WIDGET_LOG_PANEL: {
-				Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
+				Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 				AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 				cur_company.Restore();
 				if (log == NULL) return;
@@ -914,7 +914,7 @@
 		this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
 		ai_debug_company = show_ai;
 
-		Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
+		Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 		cur_company.Restore();
 		this->vscroll.SetCount((log == NULL) ? 0 : log->used);
@@ -1009,7 +1009,7 @@
 		/* If the log message is related to the active company tab, check the break string */
 		if (data == ai_debug_company && this->break_check_enabled && !StrEmpty(this->edit_str_buf)) {
 			/* Get the log instance of the active company */
-			Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
+			Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 			AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
 			if (log != NULL && case_sensitive_break_check?
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -1204,7 +1204,7 @@
 	 */
 	const Station *st = GetTargetAirportIfValid(v);
 	if (st == NULL) {
-		Backup<CompanyByte> cur_company(_current_company, v->owner);
+		Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
 		CommandCost ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
 		cur_company.Restore();
 
@@ -1510,7 +1510,7 @@
 
 	/* Send the helicopter to a hangar if needed for replacement */
 	if (v->NeedsAutomaticServicing()) {
-		Backup<CompanyByte> cur_company(_current_company, v->owner);
+		Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
 		DoCommand(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
 		cur_company.Restore();
 	}
@@ -1562,7 +1562,7 @@
 
 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
 	if (v->NeedsAutomaticServicing()) {
-		Backup<CompanyByte> cur_company(_current_company, v->owner);
+		Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
 		DoCommand(v->tile, v->index, DEPOT_SERVICE, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
 		cur_company.Restore();
 	}
--- a/src/core/backup_type.hpp
+++ b/src/core/backup_type.hpp
@@ -12,6 +12,8 @@
 #ifndef BACKUP_TYPE_HPP
 #define BACKUP_TYPE_HPP
 
+#include "../debug.h"
+
 /**
  * Class to backup a specific variable and restore it later.
  * The variable is not restored automatically, but assertions make sure it is restored.
@@ -22,16 +24,20 @@
 	/**
 	 * Backup variable.
 	 * @param original Variable to backup.
+	 * @param file Filename for debug output. Use FILE_LINE macro.
+	 * @param line Linenumber for debug output. Use FILE_LINE macro.
 	 */
-	Backup(T &original) : original(original), valid(true), original_value(original) {}
+	Backup(T &original, const char * const file, const int line) : original(original), valid(true), original_value(original), file(file), line(line) {}
 
 	/**
 	 * Backup variable and switch to new value.
 	 * @param original Variable to backup.
 	 * @param new_value New value for variable.
+	 * @param file Filename for debug output. Use FILE_LINE macro.
+	 * @param line Linenumber for debug output. Use FILE_LINE macro.
 	 */
 	template <typename U>
-	Backup(T &original, const U &new_value) : original(original), valid(true), original_value(original)
+	Backup(T &original, const U &new_value, const char * const file, const int line) : original(original), valid(true), original_value(original), file(file), line(line)
 	{
 		/* Note: We use a separate typename U, so type conversions are handled by assignment operator. */
 		original = new_value;
@@ -43,7 +49,13 @@
 	~Backup()
 	{
 		/* Check whether restoration was done */
-		assert(!this->valid);
+		if (this->valid)
+		{
+			/* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown.
+			 * Exceptions are especially used to abort world generation. */
+			DEBUG(misc, 0, "%s:%d: Backupped value was not restored!", this->file, this->line);
+			this->Restore();
+		}
 	}
 
 	/**
@@ -129,6 +141,9 @@
 	T &original;
 	bool valid;
 	T original_value;
+
+	const char * const file;
+	const int line;
 };
 
 #endif /* BACKUP_TYPE_HPP */
--- a/src/debug.h
+++ b/src/debug.h
@@ -53,6 +53,9 @@
 void SetDebugString(const char *s);
 const char *GetDebugString();
 
+/* Shorter form for passing filename and linenumber */
+#define FILE_LINE __FILE__, __LINE__
+
 /* Used for profiling
  *
  * Usage:
--- a/src/disaster_cmd.cpp
+++ b/src/disaster_cmd.cpp
@@ -73,7 +73,7 @@
 	switch (GetTileType(tile)) {
 		case MP_RAILWAY:
 			if (Company::IsHumanID(GetTileOwner(tile))) {
-				Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
+				Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
 				DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 				cur_company.Restore();
 
@@ -83,7 +83,7 @@
 			break;
 
 		case MP_HOUSE: {
-			Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+			Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 			DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 			cur_company.Restore();
 			break;
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -305,7 +305,7 @@
 #endif /* ENABLE_NETWORK */
 
 	Town *t;
-	Backup<CompanyByte> cur_company(_current_company, old_owner);
+	Backup<CompanyByte> cur_company(_current_company, old_owner, FILE_LINE);
 
 	assert(old_owner != new_owner);
 
@@ -327,7 +327,7 @@
 		}
 
 		/* Sell all the shares that people have on this company */
-		Backup<CompanyByte> cur_company2(_current_company);
+		Backup<CompanyByte> cur_company2(_current_company, FILE_LINE);
 		c = Company::Get(old_owner);
 		for (i = 0; i < 4; i++) {
 			cur_company2.Change(c->share_owners[i]);
@@ -553,7 +553,7 @@
 	Station *st;
 	Company *c;
 
-	Backup<CompanyByte> cur_company(_current_company);
+	Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
 	FOR_ALL_STATIONS(st) {
 		cur_company.Change(st->owner);
 		CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
@@ -688,7 +688,7 @@
 {
 	const Company *c;
 
-	Backup<CompanyByte> cur_company(_current_company);
+	Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
 	FOR_ALL_COMPANIES(c) {
 		cur_company.Change(c->index);
 
@@ -1027,7 +1027,7 @@
 
 	if (this->visual_profit == 0) return;
 
-	Backup<CompanyByte> cur_company(_current_company, this->front->owner);
+	Backup<CompanyByte> cur_company(_current_company, this->front->owner, FILE_LINE);
 
 	SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
 	this->front->profit_this_year += this->visual_profit << 8;
@@ -1458,7 +1458,7 @@
 	}
 
 	value = CalculateCompanyValue(c) >> 2;
-	Backup<CompanyByte> cur_company(_current_company);
+	Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
 	for (i = 0; i != 4; i++) {
 		if (c->share_owners[i] != COMPANY_SPECTATOR) {
 			cur_company.Change(c->share_owners[i]);
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -1043,7 +1043,7 @@
 	if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
 		/* found a tree */
 
-		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 
 		_industry_sound_ctr = 1;
 		_industry_sound_tile = tile;
@@ -1372,7 +1372,7 @@
 				}
 
 				/* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
-				Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
+				Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 				CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
 				cur_company.Restore();
 
@@ -1484,7 +1484,7 @@
 
 	/* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
 	 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
-	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 
 	TILE_LOOP(tile_walk, size_x, size_y, cur_tile) {
 		curh = TileHeight(tile_walk);
@@ -1788,7 +1788,7 @@
 	if (_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry()) {
 		if (flags & DC_EXEC) {
 			/* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
-			Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
+			Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 			/* Prospecting has a chance to fail, however we cannot guarantee that something can
 			 * be built on the map, so the chance gets lower when the map is fuller, but there
 			 * is nothing we can really do about that. */
@@ -1890,7 +1890,7 @@
  */
 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
 {
-	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 
 	IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
 
@@ -2414,7 +2414,7 @@
 		return;  // Nothing to do? get out
 	}
 
-	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 
 	/* perform the required industry changes for the day */
 	for (uint16 j = 0; j < change_loop; j++) {
@@ -2439,7 +2439,7 @@
 void IndustryMonthlyLoop()
 {
 	Industry *i;
-	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 
 	FOR_ALL_INDUSTRIES(i) {
 		UpdateIndustryStatistics(i);
--- a/src/industry_gui.cpp
+++ b/src/industry_gui.cpp
@@ -523,7 +523,7 @@
 				return;
 			}
 
-			Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+			Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 			_generating_world = true;
 			_ignore_restrictions = true;
 
--- a/src/misc_cmd.cpp
+++ b/src/misc_cmd.cpp
@@ -230,7 +230,7 @@
 
 	if (flags & DC_EXEC) {
 		/* Add money to company */
-		Backup<CompanyByte> cur_company(_current_company, dest_company);
+		Backup<CompanyByte> cur_company(_current_company, dest_company, FILE_LINE);
 		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
 		cur_company.Restore();
 	}
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -1216,7 +1216,7 @@
 
 		/* All these actions has to be done from OWNER_NONE
 		 *  for multiplayer compatibility */
-		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 
 		AnimateAnimatedTiles();
 		IncreaseDate();
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -642,7 +642,7 @@
 
 		TrackBits to_remove = lower_track & rail_bits;
 		if (to_remove != 0) {
-			Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
+			Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
 			flooded = DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL).Succeeded();
 			cur_company.Restore();
 			if (!flooded) return flooded; // not yet floodable
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -1160,7 +1160,7 @@
 static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
 {
 	/* The 'current' company is not necessarily the owner of the vehicle. */
-	Backup<CompanyByte> cur_company(_current_company, c);
+	Backup<CompanyByte> cur_company(_current_company, c, FILE_LINE);
 
 	CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NONE, CMD_BUILD_ROAD);
 
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -1571,7 +1571,7 @@
 			if (IsBuoyTile(t) || IsDriveThroughStopTile(t) || IsTileType(t, MP_WATER)) {
 				Owner o = GetTileOwner(t);
 				if (o < MAX_COMPANIES && !Company::IsValidID(o)) {
-					Backup<CompanyByte> cur_company(_current_company, o);
+					Backup<CompanyByte> cur_company(_current_company, o, FILE_LINE);
 					ChangeTileOwner(t, o, INVALID_OWNER);
 					cur_company.Restore();
 				}
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -516,7 +516,7 @@
 		}
 	}
 
-	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 
 	if ((hs->building_flags & BUILDING_HAS_1_TILE) &&
 			HasBit(t->flags, TOWN_IS_FUNDED) &&
@@ -1297,7 +1297,7 @@
 	};
 
 	/* Current "company" is a town */
-	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 
 	TileIndex tile = t->xy; // The tile we are working with ATM
 
@@ -2383,7 +2383,7 @@
 		return false;
 	}
 
-	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
 	CommandCost r = DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 	cur_company.Restore();
 
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -773,7 +773,7 @@
 		}
 	}
 
-	Backup<CompanyByte> cur_company(_current_company);
+	Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
 	for (AutoreplaceMap::iterator it = _vehicles_to_autoreplace.Begin(); it != _vehicles_to_autoreplace.End(); it++) {
 		v = it->first;
 		/* Autoreplace needs the current company set as the vehicle owner */
@@ -1112,7 +1112,7 @@
 		}
 
 		if (t.IsRefit()) {
-			Backup<CompanyByte> cur_company(_current_company, v->owner);
+			Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
 			CommandCost cost = DoCommand(v->tile, v->index, t.GetRefitCargo() | t.GetRefitSubtype() << 8, DC_EXEC, GetCmdRefitVeh(v));
 			cur_company.Restore();
 
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -882,7 +882,7 @@
 
 	bool flooded = false; // Will be set to true if something is changed.
 
-	Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
 
 	Slope tileh = GetTileSlope(target, NULL);
 	if (tileh != SLOPE_FLAT) {
@@ -942,7 +942,7 @@
  */
 static void DoDryUp(TileIndex tile)
 {
-	Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
+	Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
 
 	switch (GetTileType(tile)) {
 		case MP_RAILWAY: