Changeset - r25681:3f3776f44d48
[Not reviewed]
master
0 2 0
Patric Stout - 3 years ago 2021-06-14 12:55:37
truebrain@openttd.org
Codechange: use SLE_STRUCT(LIST) for Linkgraph chunks
2 files changed with 106 insertions and 90 deletions:
0 comments (0 inline, 0 general)
src/linkgraph/linkgraph.h
Show inline comments
 
@@ -524,13 +524,14 @@ public:
 

	
 
protected:
 
	friend class LinkGraph::ConstNode;
 
	friend class LinkGraph::Node;
 
	friend SaveLoadTable GetLinkGraphDesc();
 
	friend SaveLoadTable GetLinkGraphJobDesc();
 
	friend void SaveLoad_LinkGraph(LinkGraph &lg);
 
	friend class SlLinkgraphNode;
 
	friend class SlLinkgraphEdge;
 

	
 
	CargoID cargo;         ///< Cargo of this component's link graph.
 
	Date last_compression; ///< Last time the capacities and supplies were compressed.
 
	NodeVector nodes;      ///< Nodes in the component.
 
	EdgeMatrix edges;      ///< Edges in the component.
 
};
src/saveload/linkgraph_sl.cpp
Show inline comments
 
@@ -18,28 +18,125 @@
 
#include "../safeguards.h"
 

	
 
typedef LinkGraph::BaseNode Node;
 
typedef LinkGraph::BaseEdge Edge;
 

	
 
static uint16 _num_nodes;
 
static LinkGraph *_linkgraph; ///< Contains the current linkgraph being saved/loaded.
 
static NodeID _linkgraph_from; ///< Contains the current "from" node being saved/loaded.
 

	
 
class SlLinkgraphEdge : public DefaultSaveLoadHandler<SlLinkgraphEdge, Node> {
 
public:
 
	inline static const SaveLoad description[] = {
 
		SLE_CONDNULL(4, SL_MIN_VERSION, SLV_191), // distance
 
		    SLE_VAR(Edge, capacity,                 SLE_UINT32),
 
		    SLE_VAR(Edge, usage,                    SLE_UINT32),
 
		    SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
 
		SLE_CONDVAR(Edge, last_restricted_update,   SLE_INT32, SLV_187, SL_MAX_VERSION),
 
		    SLE_VAR(Edge, next_edge,                SLE_UINT16),
 
	};
 

	
 
	void Save(Node *bn) const override
 
	{
 
		for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
 
			SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(Node *bn) const override
 
	{
 
		uint16 max_size = _linkgraph->Size();
 

	
 
		if (IsSavegameVersionBefore(SLV_191)) {
 
			/* We used to save the full matrix ... */
 
			for (NodeID to = 0; to < max_size; ++to) {
 
				SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
 
			}
 
			return;
 
		}
 

	
 
		/* ... but as that wasted a lot of space we save a sparse matrix now. */
 
		for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
 
			if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
 
			SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
 
		}
 
	}
 
};
 

	
 
class SlLinkgraphNode : public DefaultSaveLoadHandler<SlLinkgraphNode, LinkGraph> {
 
public:
 
	inline static const SaveLoad description[] = {
 
		SLE_CONDVAR(Node, xy,          SLE_UINT32, SLV_191, SL_MAX_VERSION),
 
		    SLE_VAR(Node, supply,      SLE_UINT32),
 
		    SLE_VAR(Node, demand,      SLE_UINT32),
 
		    SLE_VAR(Node, station,     SLE_UINT16),
 
		    SLE_VAR(Node, last_update, SLE_INT32),
 
		SLEG_STRUCTLIST(SlLinkgraphEdge),
 
	};
 

	
 
	void Save(LinkGraph *lg) const override
 
	{
 
		_linkgraph = lg;
 

	
 
		for (NodeID from = 0; from < lg->Size(); ++from) {
 
			_linkgraph_from = from;
 
			SlObject(&lg->nodes[from], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(LinkGraph *lg) const override
 
	{
 
		_linkgraph = lg;
 

	
 
		lg->Init(_num_nodes);
 
		for (NodeID from = 0; from < _num_nodes; ++from) {
 
			_linkgraph_from = from;
 
			SlObject(&lg->nodes[from], this->GetDescription());
 
		}
 
	}
 
};
 

	
 
/**
 
 * Get a SaveLoad array for a link graph.
 
 * @return SaveLoad array for link graph.
 
 */
 
SaveLoadTable GetLinkGraphDesc()
 
{
 
	static const SaveLoad link_graph_desc[] = {
 
		 SLE_VAR(LinkGraph, last_compression, SLE_INT32),
 
		SLEG_VAR(_num_nodes,                  SLE_UINT16),
 
		 SLE_VAR(LinkGraph, cargo,            SLE_UINT8),
 
		SLEG_STRUCTLIST(SlLinkgraphNode),
 
	};
 
	return link_graph_desc;
 
}
 

	
 
/**
 
 * Proxy to reuse LinkGraph to save/load a LinkGraphJob.
 
 * One of the members of a LinkGraphJob is a LinkGraph, but SLEG_STRUCT()
 
 * doesn't allow us to select a member. So instead, we add a bit of glue to
 
 * accept a LinkGraphJob, get the LinkGraph, and use that to call the
 
 * save/load routines for a regular LinkGraph.
 
 */
 
class SlLinkgraphJobProxy : public DefaultSaveLoadHandler<SlLinkgraphJobProxy, LinkGraphJob> {
 
public:
 
	inline static const SaveLoad description[] = {{}}; // Needed to keep DefaultSaveLoadHandler happy.
 
	SaveLoadTable GetDescription() const override { return GetLinkGraphDesc(); }
 

	
 
	void Save(LinkGraphJob *lgj) const override
 
	{
 
		SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
 
	}
 

	
 
	void Load(LinkGraphJob *lgj) const override
 
	{
 
		SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
 
	}
 
};
 

	
 
/**
 
 * Get a SaveLoad array for a link graph job. The settings struct is derived from
 
 * the global settings saveload array. The exact entries are calculated when the function
 
 * is called the first time.
 
 * It's necessary to keep a copy of the settings for each link graph job so that you can
 
 * change the settings while in-game and still not mess with current link graph runs.
 
 * Of course the settings have to be saved and loaded, too, to avoid desyncs.
 
@@ -50,12 +147,13 @@ SaveLoadTable GetLinkGraphJobDesc()
 
	static std::vector<SaveLoad> saveloads;
 
	static const char *prefix = "linkgraph.";
 

	
 
	static const SaveLoad job_desc[] = {
 
		SLE_VAR(LinkGraphJob, join_date,        SLE_INT32),
 
		SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
 
		SLEG_STRUCT(SlLinkgraphJobProxy),
 
	};
 

	
 
	/* The member offset arithmetic below is only valid if the types in question
 
	 * are standard layout types. Otherwise, it would be undefined behaviour. */
 
	static_assert(std::is_standard_layout<LinkGraphSettings>::value, "LinkGraphSettings needs to be a standard layout type");
 

	
 
@@ -90,62 +188,12 @@ SaveLoadTable GetLinkGraphScheduleDesc()
 
		SLE_REFLIST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
 
		SLE_REFLIST(LinkGraphSchedule, running,  REF_LINK_GRAPH_JOB),
 
	};
 
	return schedule_desc;
 
}
 

	
 
/* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
 

	
 
/**
 
 * SaveLoad desc for a link graph node.
 
 */
 
static const SaveLoad _node_desc[] = {
 
	SLE_CONDVAR(Node, xy,          SLE_UINT32, SLV_191, SL_MAX_VERSION),
 
	    SLE_VAR(Node, supply,      SLE_UINT32),
 
	    SLE_VAR(Node, demand,      SLE_UINT32),
 
	    SLE_VAR(Node, station,     SLE_UINT16),
 
	    SLE_VAR(Node, last_update, SLE_INT32),
 
};
 

	
 
/**
 
 * SaveLoad desc for a link graph edge.
 
 */
 
static const SaveLoad _edge_desc[] = {
 
	SLE_CONDNULL(4, SL_MIN_VERSION, SLV_191), // distance
 
	     SLE_VAR(Edge, capacity,                 SLE_UINT32),
 
	     SLE_VAR(Edge, usage,                    SLE_UINT32),
 
	     SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
 
	 SLE_CONDVAR(Edge, last_restricted_update,   SLE_INT32, SLV_187, SL_MAX_VERSION),
 
	     SLE_VAR(Edge, next_edge,                SLE_UINT16),
 
};
 

	
 
/**
 
 * Save/load a link graph.
 
 * @param lg Link graph to be saved or loaded.
 
 */
 
void SaveLoad_LinkGraph(LinkGraph &lg)
 
{
 
	uint16 size = lg.Size();
 
	for (NodeID from = 0; from < size; ++from) {
 
		Node *node = &lg.nodes[from];
 
		SlObject(node, _node_desc);
 
		if (IsSavegameVersionBefore(SLV_191)) {
 
			/* We used to save the full matrix ... */
 
			for (NodeID to = 0; to < size; ++to) {
 
				SlObject(&lg.edges[from][to], _edge_desc);
 
			}
 
		} else {
 
			/* ... but as that wasted a lot of space we save a sparse matrix now. */
 
			for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
 
				if (to >= size) SlErrorCorrupt("Link graph structure overflow");
 
				SlObject(&lg.edges[from][to], _edge_desc);
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * Spawn the threads for running link graph calculations.
 
 * Has to be done after loading as the cargo classes might have changed.
 
 */
 
void AfterLoadLinkGraphs()
 
{
 
@@ -171,91 +219,58 @@ void AfterLoadLinkGraphs()
 
	if (!_networking || _network_server) {
 
		AfterLoad_LinkGraphPauseControl();
 
	}
 
}
 

	
 
/**
 
 * Save a link graph.
 
 * @param lg LinkGraph to be saved.
 
 */
 
static void DoSave_LGRP(LinkGraph *lg)
 
{
 
	_num_nodes = lg->Size();
 
	SlObject(lg, GetLinkGraphDesc());
 
	SaveLoad_LinkGraph(*lg);
 
}
 

	
 
/**
 
 * Save all link graphs.
 
 */
 
static void Save_LGRP()
 
{
 
	for (LinkGraph *lg : LinkGraph::Iterate()) {
 
		_num_nodes = lg->Size();
 

	
 
		SlSetArrayIndex(lg->index);
 
		SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
 
		SlObject(lg, GetLinkGraphDesc());
 
	}
 
}
 

	
 
/**
 
 * Load all link graphs.
 
 */
 
static void Load_LGRP()
 
{
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		if (!LinkGraph::CanAllocateItem()) {
 
			/* Impossible as they have been present in previous game. */
 
			NOT_REACHED();
 
		}
 
		LinkGraph *lg = new (index) LinkGraph();
 
		SlObject(lg, GetLinkGraphDesc());
 
		lg->Init(_num_nodes);
 
		SaveLoad_LinkGraph(*lg);
 
	}
 
}
 

	
 
/**
 
 * Save a link graph job.
 
 * @param lgj LinkGraphJob to be saved.
 
 */
 
static void DoSave_LGRJ(LinkGraphJob *lgj)
 
{
 
	SlObject(lgj, GetLinkGraphJobDesc());
 
	_num_nodes = lgj->Size();
 
	SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
 
	SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
 
}
 

	
 
/**
 
 * Save all link graph jobs.
 
 */
 
static void Save_LGRJ()
 
{
 
	for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
 
		_num_nodes = lgj->Size();
 

	
 
		SlSetArrayIndex(lgj->index);
 
		SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
 
		SlObject(lgj, GetLinkGraphJobDesc());
 
	}
 
}
 

	
 
/**
 
 * Load all link graph jobs.
 
 */
 
static void Load_LGRJ()
 
{
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		if (!LinkGraphJob::CanAllocateItem()) {
 
			/* Impossible as they have been present in previous game. */
 
			NOT_REACHED();
 
		}
 
		LinkGraphJob *lgj = new (index) LinkGraphJob();
 
		SlObject(lgj, GetLinkGraphJobDesc());
 
		LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
 
		SlObject(&lg, GetLinkGraphDesc());
 
		lg.Init(_num_nodes);
 
		SaveLoad_LinkGraph(lg);
 
	}
 
}
 

	
 
/**
 
 * Save the link graph schedule.
 
 */
0 comments (0 inline, 0 general)