OpenTTD
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 
27 
31 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
32 private:
36  struct EdgeAnnotation {
37  uint demand;
39  uint flow;
40  void Init();
41  };
42 
46  struct NodeAnnotation {
48  PathList paths;
50  void Init(uint supply);
51  };
52 
55 
56  friend const SaveLoad *GetLinkGraphJobDesc();
57  friend class LinkGraphSchedule;
58 
59 protected:
66 
67  void EraseFlows(NodeID from);
68  void JoinThread();
69  void SpawnThread();
70 
71 public:
72 
77  class Edge : public LinkGraph::ConstEdge {
78  private:
80  public:
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> {
149  public:
157  LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, current),
158  base_anno(base_anno) {}
159 
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:
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 
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:
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 
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;
429  uint flow;
430  NodeID node;
431  NodeID origin;
434 };
435 
436 #endif /* LINKGRAPHJOB_H */