OpenTTD

linkgraph_sl.cpp
Go to the documentation of this file.
1 /* $Id: linkgraph_sl.cpp 27178 2015-03-07 18:27:01Z frosch $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
9
12 #include "../stdafx.h"
13 #include "../linkgraph/linkgraph.h"
14 #include "../linkgraph/linkgraphjob.h"
15 #include "../linkgraph/linkgraphschedule.h"
16 #include "../settings_internal.h"
17 #include "saveload.h"
18
19 #include "../safeguards.h"
20
21 typedef LinkGraph::BaseNode Node;
22 typedef LinkGraph::BaseEdge Edge;
23
24 const SettingDesc *GetSettingDescription(uint index);
25
26 static uint16 _num_nodes;
27
32 const SaveLoad *GetLinkGraphDesc()
33 {
34 static const SaveLoad link_graph_desc[] = {
35 SLE_VAR(LinkGraph, last_compression, SLE_INT32),
36 SLEG_VAR(_num_nodes, SLE_UINT16),
37 SLE_VAR(LinkGraph, cargo, SLE_UINT8),
38 SLE_END()
39 };
40 return link_graph_desc;
41 }
42
52 const SaveLoad *GetLinkGraphJobDesc()
53 {
54 static SmallVector<SaveLoad, 16> saveloads;
55 static const char *prefix = "linkgraph.";
56
57 /* Build the SaveLoad array on first call and don't touch it later on */
58 if (saveloads.Length() == 0) {
59 size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
60 size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
61
62 size_t prefixlen = strlen(prefix);
63
64 int setting = 0;
65 const SettingDesc *desc = GetSettingDescription(setting);
66 while (desc->save.cmd != SL_END) {
67 if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
68 SaveLoad sl = desc->save;
69 char *&address = reinterpret_cast<char *&>(sl.address);
70 address -= offset_gamesettings;
71 address += offset_component;
72 *(saveloads.Append()) = sl;
73 }
74 desc = GetSettingDescription(++setting);
75 }
76
77 const SaveLoad job_desc[] = {
78 SLE_VAR(LinkGraphJob, join_date, SLE_INT32),
79 SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
80 SLE_END()
81 };
82
83 int i = 0;
84 do {
85 *(saveloads.Append()) = job_desc[i++];
86 } while (saveloads[saveloads.Length() - 1].cmd != SL_END);
87 }
88
89 return &saveloads[0];
90 }
91
96 const SaveLoad *GetLinkGraphScheduleDesc()
97 {
98 static const SaveLoad schedule_desc[] = {
99 SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
100 SLE_LST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB),
101 SLE_END()
102 };
103 return schedule_desc;
104 }
105
106 /* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
107
111 static const SaveLoad _node_desc[] = {
112 SLE_CONDVAR(Node, xy, SLE_UINT32, 191, SL_MAX_VERSION),
113 SLE_VAR(Node, supply, SLE_UINT32),
114 SLE_VAR(Node, demand, SLE_UINT32),
115 SLE_VAR(Node, station, SLE_UINT16),
116 SLE_VAR(Node, last_update, SLE_INT32),
117 SLE_END()
118 };
119
123 static const SaveLoad _edge_desc[] = {
124 SLE_CONDNULL(4, 0, 190), // distance
125 SLE_VAR(Edge, capacity, SLE_UINT32),
126 SLE_VAR(Edge, usage, SLE_UINT32),
127 SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
128 SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, 187, SL_MAX_VERSION),
129 SLE_VAR(Edge, next_edge, SLE_UINT16),
130 SLE_END()
131 };
132
137 void SaveLoad_LinkGraph(LinkGraph &lg)
138 {
139 uint size = lg.Size();
140 for (NodeID from = 0; from < size; ++from) {
141 Node *node = &lg.nodes[from];
142 SlObject(node, _node_desc);
143 if (IsSavegameVersionBefore(191)) {
144 /* We used to save the full matrix ... */
145 for (NodeID to = 0; to < size; ++to) {
146 SlObject(&lg.edges[from][to], _edge_desc);
147 }
148 } else {
149 /* ... but as that wasted a lot of space we save a sparse matrix now. */
150 for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
151 SlObject(&lg.edges[from][to], _edge_desc);
152 }
153 }
154 }
155 }
156
161 static void DoSave_LGRJ(LinkGraphJob *lgj)
162 {
163 SlObject(lgj, GetLinkGraphJobDesc());
164 _num_nodes = lgj->Size();
165 SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
166 SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
167 }
168
173 static void DoSave_LGRP(LinkGraph *lg)
174 {
175 _num_nodes = lg->Size();
176 SlObject(lg, GetLinkGraphDesc());
177 SaveLoad_LinkGraph(*lg);
178 }
179
183 static void Load_LGRP()
184 {
185 int index;
186 while ((index = SlIterateArray()) != -1) {
187 if (!LinkGraph::CanAllocateItem()) {
188 /* Impossible as they have been present in previous game. */
189 NOT_REACHED();
190 }
191 LinkGraph *lg = new (index) LinkGraph();
192 SlObject(lg, GetLinkGraphDesc());
193 lg->Init(_num_nodes);
194 SaveLoad_LinkGraph(*lg);
195 }
196 }
197
201 static void Load_LGRJ()
202 {
203 int index;
204 while ((index = SlIterateArray()) != -1) {
205 if (!LinkGraphJob::CanAllocateItem()) {
206 /* Impossible as they have been present in previous game. */
207 NOT_REACHED();
208 }
209 LinkGraphJob *lgj = new (index) LinkGraphJob();
210 SlObject(lgj, GetLinkGraphJobDesc());
211 LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
212 SlObject(&lg, GetLinkGraphDesc());
213 lg.Init(_num_nodes);
214 SaveLoad_LinkGraph(lg);
215 }
216 }
217
221 static void Load_LGRS()
222 {
223 SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
224 }
225
230 void AfterLoadLinkGraphs()
231 {
232 if (IsSavegameVersionBefore(191)) {
233 LinkGraph *lg;
234 FOR_ALL_LINK_GRAPHS(lg) {
235 for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
236 (*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
237 }
238 }
239
240 LinkGraphJob *lgj;
241 FOR_ALL_LINK_GRAPH_JOBS(lgj) {
242 lg = &(const_cast<LinkGraph &>(lgj->Graph()));
243 for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
244 (*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
245 }
246 }
247 }
248
249 LinkGraphSchedule::instance.SpawnAll();
250 }
251
255 static void Save_LGRP()
256 {
257 LinkGraph *lg;
258 FOR_ALL_LINK_GRAPHS(lg) {
259 SlSetArrayIndex(lg->index);
260 SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
261 }
262 }
263
267 static void Save_LGRJ()
268 {
269 LinkGraphJob *lgj;
270 FOR_ALL_LINK_GRAPH_JOBS(lgj) {
271 SlSetArrayIndex(lgj->index);
272 SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
273 }
274 }
275
279 static void Save_LGRS()
280 {
281 SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
282 }
283
287 static void Ptrs_LGRS()
288 {
289 SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
290 }
291
292 extern const ChunkHandler _linkgraph_chunk_handlers[] = {
293 { 'LGRP', Save_LGRP, Load_LGRP, NULL, NULL, CH_ARRAY },
294 { 'LGRJ', Save_LGRJ, Load_LGRJ, NULL, NULL, CH_ARRAY },
295 { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, NULL, CH_LAST }
296 };
SLE_CONDNULL
#define SLE_CONDNULL(length, from, to)
Empty space in some savegame versions.
Definition: saveload.h:344
Load_LGRJ
static void Load_LGRJ()
Load all link graph jobs.
Definition: linkgraph_sl.cpp:201
GetLinkGraphDesc
const SaveLoad * GetLinkGraphDesc()
Get a SaveLoad array for a link graph.
Definition: linkgraph_sl.cpp:32
DoSave_LGRJ
static void DoSave_LGRJ(LinkGraphJob *lgj)
Save a link graph job.
Definition: linkgraph_sl.cpp:161
LinkGraph::BaseEdge
An edge in the link graph.
Definition: linkgraph.h:63
Ptrs_LGRS
static void Ptrs_LGRS()
Substitute pointers in link graph schedule.
Definition: linkgraph_sl.cpp:287
GameSettings
All settings together for the game.
Definition: settings_type.h:542
LinkGraphSchedule::SpawnAll
void SpawnAll()
Start all threads in the running list.
Definition: linkgraphschedule.cpp:87
SLE_LST
#define SLE_LST(base, variable, type)
Storage of a list in every savegame version.
Definition: saveload.h:330
REF_LINK_GRAPH_JOB
Load/save a reference to a link graph job.
Definition: saveload.h:92
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
LinkGraphSchedule
Definition: linkgraphschedule.h:38
SaveLoad::address
void * address
address of variable OR offset of variable in the struct (max offset is 65536)
Definition: saveload.h:219
SmallVector
Simple vector template class.
Definition: smallvec_type.hpp:29
SLEG_VAR
#define SLEG_VAR(variable, type)
Storage of a global variable in every savegame version.
Definition: saveload.h:418
SettingDescBase::name
const char * name
name of the setting. Used in configuration file and for console
Definition: settings_internal.h:95
SmallVector::Append
T * Append(uint to_add=1)
Append an item and return it.
Definition: smallvec_type.hpp:134
Load_LGRS
static void Load_LGRS()
Load the link graph schedule.
Definition: linkgraph_sl.cpp:221
LinkGraph
A connected component of a link graph.
Definition: linkgraph.h:40
GetLinkGraphJobDesc
const SaveLoad * GetLinkGraphJobDesc()
Get a SaveLoad array for a link graph job.
Definition: linkgraph_sl.cpp:52
SettingDesc::save
SaveLoad save
Internal structure (going to savegame, parts to config)
Definition: settings_internal.h:113
LinkGraph::Size
uint Size() const
Get the current size of the component.
Definition: linkgraph.h:499
saveload.h
Functions/types related to saving and loading games.
SLE_CONDVAR
#define SLE_CONDVAR(base, variable, type, from, to)
Storage of a variable in some savegame versions.
Definition: saveload.h:246
_node_desc
static const SaveLoad _node_desc[]
SaveLoad desc for a link graph node.
Definition: linkgraph_sl.cpp:111
LinkGraph::Node
Updatable node class.
Definition: linkgraph.h:374
SmallVector::Length
uint Length() const
Get the number of items in the list.
Definition: smallvec_type.hpp:262
Save_LGRP
static void Save_LGRP()
Save all link graphs.
Definition: linkgraph_sl.cpp:255
LinkGraphSchedule::instance
static LinkGraphSchedule instance
Static instance of LinkGraphSchedule.
Definition: linkgraphschedule.h:54
_edge_desc
static const SaveLoad _edge_desc[]
SaveLoad desc for a link graph edge.
Definition: linkgraph_sl.cpp:123
Save_LGRJ
static void Save_LGRJ()
Save all link graph jobs.
Definition: linkgraph_sl.cpp:267
SettingDesc
Definition: settings_internal.h:111
LinkGraph::edges
EdgeMatrix edges
Edges in the component.
Definition: linkgraph.h:536
GetLinkGraphScheduleDesc
const SaveLoad * GetLinkGraphScheduleDesc()
Get a SaveLoad array for the link graph schedule.
Definition: linkgraph_sl.cpp:96
AfterLoadLinkGraphs
void AfterLoadLinkGraphs()
Spawn the threads for running link graph calculations.
Definition: linkgraph_sl.cpp:230
SL_MAX_VERSION
#define SL_MAX_VERSION
Highest possible savegame version.
Definition: saveload.h:96
IsSavegameVersionBefore
static bool IsSavegameVersionBefore(uint16 major, byte minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:465
LinkGraph::Edge
An updatable edge class.
Definition: linkgraph.h:293
SlIterateArray
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:828
ChunkHandler
Handlers and description of chunk.
Definition: saveload.h:66
SLE_END
#define SLE_END()
End marker of a struct/class save or load.
Definition: saveload.h:353
LinkGraph::Init
void Init(uint size)
Resize the component and fill it with empty nodes and edges.
Definition: linkgraph.cpp:282
Save_LGRS
static void Save_LGRS()
Save the link graph schedule.
Definition: linkgraph_sl.cpp:279
LinkGraph::BaseNode
Node of the link graph.
Definition: linkgraph.h:48
SaveLoad::cmd
SaveLoadType cmd
the action to take with the saved/loaded type, All types need different action
Definition: saveload.h:210
SlObject
void SlObject(void *object, const SaveLoad *sld)
Main SaveLoad function.
Definition: saveload.cpp:1612
LinkGraphJob::Size
uint Size() const
Get the size of the underlying link graph.
Definition: linkgraphjob.h:312
LinkGraphJob::Graph
const LinkGraph & Graph() const
Get a reference to the underlying link graph.
Definition: linkgraphjob.h:336
Pool::PoolItem<&_link_graph_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
SlAutolength
void SlAutolength(AutolengthProc *proc, void *arg)
Do something of which I have no idea what it is :P.
Definition: saveload.cpp:1640
SaveLoad
SaveLoad type struct.
Definition: saveload.h:208
SLE_VAR
#define SLE_VAR(base, variable, type)
Storage of a variable in every version of a savegame.
Definition: saveload.h:296
Load_LGRP
static void Load_LGRP()
Load all link graphs.
Definition: linkgraph_sl.cpp:183
REF_LINK_GRAPH
Load/save a reference to a link graph.
Definition: saveload.h:91
DoSave_LGRP
static void DoSave_LGRP(LinkGraph *lg)
Save a link graph.
Definition: linkgraph_sl.cpp:173
LinkGraph::nodes
NodeVector nodes
Nodes in the component.
Definition: linkgraph.h:535
SpecializedStation< Station, false >::Get
static Station * Get(size_t index)
Gets station with given index.
Definition: base_station_base.h:206
SettingDesc::desc
SettingDescBase desc
Settings structure (going to configuration file)
Definition: settings_internal.h:112
Station
Station data structure.
Definition: station_base.h:446
LinkGraphJob
Class for calculation jobs to be run on link graphs.
Definition: linkgraphjob.h:31
CH_LAST
Last chunk in this array.
Definition: saveload.h:104
SaveLoad_LinkGraph
void SaveLoad_LinkGraph(LinkGraph &lg)
Save/load a link graph.
Definition: linkgraph_sl.cpp:137