OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

linkgraphjob.h
Go to the documentation of this file.
1 /* $Id: linkgraphjob.h 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 #ifndef LINKGRAPHJOB_H
13 #define LINKGRAPHJOB_H
14
15 #include "../thread/thread.h"
16 #include "linkgraph.h"
17 #include <list>
18
19 class LinkGraphJob;
20 class Path;
21 typedef std::list<Path *> PathList;
22
24 typedef Pool<LinkGraphJob, LinkGraphJobID, 32, 0xFFFF> LinkGraphJobPool;
26 extern LinkGraphJobPool _link_graph_job_pool;
27
31 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
32 private:
36 struct EdgeAnnotation {
37 uint demand;
38 uint unsatisfied_demand;
39 uint flow;
40 void Init();
41 };
42
46 struct NodeAnnotation {
47 uint undelivered_supply;
48 PathList paths;
49 FlowStatMap flows;
50 void Init(uint supply);
51 };
52
53 typedef SmallVector<NodeAnnotation, 16> NodeAnnotationVector;
54 typedef SmallMatrix<EdgeAnnotation> EdgeAnnotationMatrix;
55
56 friend const SaveLoad *GetLinkGraphJobDesc();
57 friend class LinkGraphSchedule;
58
59 protected:
60 const LinkGraph link_graph;
61 const LinkGraphSettings settings;
62 ThreadObject *thread;
63 Date join_date;
64 NodeAnnotationVector nodes;
65 EdgeAnnotationMatrix edges;
66
67 void EraseFlows(NodeID from);
68 void JoinThread();
69 void SpawnThread();
70
71 public:
72
77 class Edge : public LinkGraph::ConstEdge {
78 private:
79 EdgeAnnotation &anno;
80 public:
86 Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
87 LinkGraph::ConstEdge(edge), anno(anno) {}
88
93 uint Demand() const { return this->anno.demand; }
94
99 uint UnsatisfiedDemand() const { return this->anno.unsatisfied_demand; }
100
105 uint Flow() const { return this->anno.flow; }
106
111 void AddFlow(uint flow) { this->anno.flow += flow; }
112
117 void RemoveFlow(uint flow)
118 {
119 assert(flow <= this->anno.flow);
120 this->anno.flow -= flow;
121 }
122
127 void AddDemand(uint demand)
128 {
129 this->anno.demand += demand;
130 this->anno.unsatisfied_demand += demand;
131 }
132
137 void SatisfyDemand(uint demand)
138 {
139 assert(demand <= this->anno.unsatisfied_demand);
140 this->anno.unsatisfied_demand -= demand;
141 }
142 };
143
147 class EdgeIterator : public LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator> {
148 EdgeAnnotation *base_anno;
149 public:
156 EdgeIterator(const LinkGraph::BaseEdge *base, EdgeAnnotation *base_anno, NodeID current) :
157 LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, current),
158 base_anno(base_anno) {}
159
165 SmallPair<NodeID, Edge> operator*() const
166 {
167 return SmallPair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
168 }
169
175 FakePointer operator->() const {
176 return FakePointer(this->operator*());
177 }
178 };
179
184 class Node : public LinkGraph::ConstNode {
185 private:
186 NodeAnnotation &node_anno;
187 EdgeAnnotation *edge_annos;
188 public:
189
195 Node (LinkGraphJob *lgj, NodeID node) :
196 LinkGraph::ConstNode(&lgj->link_graph, node),
197 node_anno(lgj->nodes[node]), edge_annos(lgj->edges[node])
198 {}
199
206 Edge operator[](NodeID to) const { return Edge(this->edges[to], this->edge_annos[to]); }
207
213 EdgeIterator Begin() const { return EdgeIterator(this->edges, this->edge_annos, index); }
214
220 EdgeIterator End() const { return EdgeIterator(this->edges, this->edge_annos, INVALID_NODE); }
221
226 uint UndeliveredSupply() const { return this->node_anno.undelivered_supply; }
227
232 FlowStatMap &Flows() { return this->node_anno.flows; }
233
238 const FlowStatMap &Flows() const { return this->node_anno.flows; }
239
245 PathList &Paths() { return this->node_anno.paths; }
246
251 const PathList &Paths() const { return this->node_anno.paths; }
252
258 void DeliverSupply(NodeID to, uint amount)
259 {
260 this->node_anno.undelivered_supply -= amount;
261 (*this)[to].AddDemand(amount);
262 }
263 };
264
269 LinkGraphJob() : settings(_settings_game.linkgraph), thread(NULL),
270 join_date(INVALID_DATE) {}
271
272 LinkGraphJob(const LinkGraph &orig);
273 ~LinkGraphJob();
274
275 void Init();
276
281 inline bool IsFinished() const { return this->join_date <= _date; }
282
287 inline Date JoinDate() const { return join_date; }
288
293 inline void ShiftJoinDate(int interval) { this->join_date += interval; }
294
299 inline const LinkGraphSettings &Settings() const { return this->settings; }
300
306 inline Node operator[](NodeID num) { return Node(this, num); }
307
312 inline uint Size() const { return this->link_graph.Size(); }
313
318 inline CargoID Cargo() const { return this->link_graph.Cargo(); }
319
324 inline Date LastCompression() const { return this->link_graph.LastCompression(); }
325
330 inline LinkGraphID LinkGraphIndex() const { return this->link_graph.index; }
331
336 inline const LinkGraph &Graph() const { return this->link_graph; }
337 };
338
339 #define FOR_ALL_LINK_GRAPH_JOBS(var) FOR_ALL_ITEMS_FROM(LinkGraphJob, link_graph_job_index, var, 0)
340
344 class Path {
345 public:
346 static Path *invalid_path;
347
348 Path(NodeID n, bool source = false);
349
351 inline NodeID GetNode() const { return this->node; }
352
354 inline NodeID GetOrigin() const { return this->origin; }
355
357 inline Path *GetParent() { return this->parent; }
358
360 inline uint GetCapacity() const { return this->capacity; }
361
363 inline int GetFreeCapacity() const { return this->free_capacity; }
364
372 inline static int GetCapacityRatio(int free, uint total)
373 {
374 return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / max(total, 1U);
375 }
376
381 inline int GetCapacityRatio() const
382 {
383 return Path::GetCapacityRatio(this->free_capacity, this->capacity);
384 }
385
387 inline uint GetDistance() const { return this->distance; }
388
390 inline void ReduceFlow(uint f) { this->flow -= f; }
391
393 inline void AddFlow(uint f) { this->flow += f; }
394
396 inline uint GetFlow() const { return this->flow; }
397
399 inline uint GetNumChildren() const { return this->num_children; }
400
404 inline void Detach()
405 {
406 if (this->parent != NULL) {
407 this->parent->num_children--;
408 this->parent = NULL;
409 }
410 }
411
412 uint AddFlow(uint f, LinkGraphJob &job, uint max_saturation);
413 void Fork(Path *base, uint cap, int free_cap, uint dist);
414
415 protected:
416
420 enum PathCapacityBoundaries {
421 PATH_CAP_MULTIPLIER = 16,
422 PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER,
423 PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER
424 };
425
426 uint distance;
427 uint capacity;
428 int free_capacity;
429 uint flow;
430 NodeID node;
431 NodeID origin;
432 uint num_children;
433 Path *parent;
434 };
435
436 #endif /* LINKGRAPHJOB_H */