# linkgraphjob.h

Go to the documentation of this file.

    00001 /* $Id: linkgraphjob.h 26347 2014-02-16 18:42:59Z fonsinchen $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #ifndef LINKGRAPHJOB_H
    00013 #define LINKGRAPHJOB_H
    00014
    00015 #include "../thread/thread.h"
    00016 #include "linkgraph.h"
    00017 #include <list>
    00018
    00019 class LinkGraphJob;
    00020 class Path;
    00021 typedef std::list<Path *> PathList;
    00022
    00024 typedef Pool<LinkGraphJob, LinkGraphJobID, 32, 0xFFFF> LinkGraphJobPool;
    00026 extern LinkGraphJobPool _link_graph_job_pool;
    00027
    00031 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
    00032 private:
    00036   struct EdgeAnnotation {
    00037     uint demand;
    00038     uint unsatisfied_demand;
    00039     uint flow;
    00040     void Init();
    00041   };
    00042
    00046   struct NodeAnnotation {
    00047     uint undelivered_supply;
    00048     PathList paths;
    00049     FlowStatMap flows;
    00050     void Init(uint supply);
    00051   };
    00052
    00053   typedef SmallVector<NodeAnnotation, 16> NodeAnnotationVector;
    00054   typedef SmallMatrix<EdgeAnnotation> EdgeAnnotationMatrix;
    00055
    00056   friend const SaveLoad *GetLinkGraphJobDesc();
    00057   friend class LinkGraphSchedule;
    00058
    00059 protected:
    00060   const LinkGraph link_graph;
    00061   const LinkGraphSettings settings;
    00062   ThreadObject *thread;
    00063   Date join_date;
    00064   NodeAnnotationVector nodes;
    00065   EdgeAnnotationMatrix edges;
    00066
    00067   void EraseFlows(NodeID from);
    00068   void JoinThread();
    00069   void SpawnThread();
    00070
    00071 public:
    00072
    00077   class Edge : public LinkGraph::ConstEdge {
    00078   private:
    00079     EdgeAnnotation &anno;
    00080   public:
    00086     Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
    00087         LinkGraph::ConstEdge(edge), anno(anno) {}
    00088
    00093     uint Demand() const { return this->anno.demand; }
    00094
    00099     uint UnsatisfiedDemand() const { return this->anno.unsatisfied_demand; }
    00100
    00105     uint Flow() const { return this->anno.flow; }
    00106
    00111     void AddFlow(uint flow) { this->anno.flow += flow; }
    00112
    00117     void RemoveFlow(uint flow)
    00118     {
    00119       assert(flow <= this->anno.flow);
    00120       this->anno.flow -= flow;
    00121     }
    00122
    00127     void AddDemand(uint demand)
    00128     {
    00129       this->anno.demand += demand;
    00130       this->anno.unsatisfied_demand += demand;
    00131     }
    00132
    00137     void SatisfyDemand(uint demand)
    00138     {
    00139       assert(demand <= this->anno.unsatisfied_demand);
    00140       this->anno.unsatisfied_demand -= demand;
    00141     }
    00142   };
    00143
    00147   class EdgeIterator : public LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator> {
    00148     EdgeAnnotation *base_anno;
    00149   public:
    00156     EdgeIterator(const LinkGraph::BaseEdge *base, EdgeAnnotation *base_anno, NodeID current) :
    00157         LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, current),
    00158         base_anno(base_anno) {}
    00159
    00165     SmallPair<NodeID, Edge> operator*() const
    00166     {
    00167       return SmallPair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
    00168     }
    00169
    00175     FakePointer operator->() const {
    00176       return FakePointer(this->operator*());
    00177     }
    00178   };
    00179
    00184   class Node : public LinkGraph::ConstNode {
    00185   private:
    00186     NodeAnnotation &node_anno;
    00187     EdgeAnnotation *edge_annos;
    00188   public:
    00189
    00195     Node (LinkGraphJob *lgj, NodeID node) :
    00196       LinkGraph::ConstNode(&lgj->link_graph, node),
    00197       node_anno(lgj->nodes[node]), edge_annos(lgj->edges[node])
    00198     {}
    00199
    00206     Edge operator[](NodeID to) const { return Edge(this->edges[to], this->edge_annos[to]); }
    00207
    00213     EdgeIterator Begin() const { return EdgeIterator(this->edges, this->edge_annos, index); }
    00214
    00220     EdgeIterator End() const { return EdgeIterator(this->edges, this->edge_annos, INVALID_NODE); }
    00221
    00226     uint UndeliveredSupply() const { return this->node_anno.undelivered_supply; }
    00227
    00232     FlowStatMap &Flows() { return this->node_anno.flows; }
    00233
    00238     const FlowStatMap &Flows() const { return this->node_anno.flows; }
    00239
    00245     PathList &Paths() { return this->node_anno.paths; }
    00246
    00251     const PathList &Paths() const { return this->node_anno.paths; }
    00252
    00258     void DeliverSupply(NodeID to, uint amount)
    00259     {
    00260       this->node_anno.undelivered_supply -= amount;
    00261       (*this)[to].AddDemand(amount);
    00262     }
    00263   };
    00264
    00269   LinkGraphJob() : settings(_settings_game.linkgraph), thread(NULL),
    00270       join_date(INVALID_DATE) {}
    00271
    00272   LinkGraphJob(const LinkGraph &orig);
    00273   ~LinkGraphJob();
    00274
    00275   void Init();
    00276
    00281   inline bool IsFinished() const { return this->join_date <= _date; }
    00282
    00287   inline Date JoinDate() const { return join_date; }
    00288
    00293   inline void ShiftJoinDate(int interval) { this->join_date += interval; }
    00294
    00299   inline const LinkGraphSettings &Settings() const { return this->settings; }
    00300
    00306   inline Node operator[](NodeID num) { return Node(this, num); }
    00307
    00312   inline uint Size() const { return this->link_graph.Size(); }
    00313
    00318   inline CargoID Cargo() const { return this->link_graph.Cargo(); }
    00319
    00324   inline Date LastCompression() const { return this->link_graph.LastCompression(); }
    00325
    00330   inline LinkGraphID LinkGraphIndex() const { return this->link_graph.index; }
    00331
    00336   inline const LinkGraph &Graph() const { return this->link_graph; }
    00337 };
    00338
    00339 #define FOR_ALL_LINK_GRAPH_JOBS(var) FOR_ALL_ITEMS_FROM(LinkGraphJob, link_graph_job_index, var, 0)
    00340
    00344 class Path {
    00345 public:
    00346   Path(NodeID n, bool source = false);
    00347
    00349   inline NodeID GetNode() const { return this->node; }
    00350
    00352   inline NodeID GetOrigin() const { return this->origin; }
    00353
    00355   inline Path *GetParent() { return this->parent; }
    00356
    00358   inline uint GetCapacity() const { return this->capacity; }
    00359
    00361   inline int GetFreeCapacity() const { return this->free_capacity; }
    00362
    00370   inline static int GetCapacityRatio(int free, uint total)
    00371   {
    00372     return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / max(total, 1U);
    00373   }
    00374
    00379   inline int GetCapacityRatio() const
    00380   {
    00381     return Path::GetCapacityRatio(this->free_capacity, this->capacity);
    00382   }
    00383
    00385   inline uint GetDistance() const { return this->distance; }
    00386
    00388   inline void ReduceFlow(uint f) { this->flow -= f; }
    00389
    00391   inline void AddFlow(uint f) { this->flow += f; }
    00392
    00394   inline uint GetFlow() const { return this->flow; }
    00395
    00397   inline uint GetNumChildren() const { return this->num_children; }
    00398
    00402   inline void Detach()
    00403   {
    00404     if (this->parent != NULL) {
    00405       this->parent->num_children--;
    00406       this->parent = NULL;
    00407     }
    00408   }
    00409
    00410   uint AddFlow(uint f, LinkGraphJob &job, uint max_saturation);
    00411   void Fork(Path *base, uint cap, int free_cap, uint dist);
    00412
    00413 protected:
    00414
    00418   enum PathCapacityBoundaries {
    00419     PATH_CAP_MULTIPLIER = 16,
    00420     PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER,
    00421     PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER
    00422   };
    00423
    00424   uint distance;
    00425   uint capacity;
    00426   int free_capacity;
    00427   uint flow;
    00428   NodeID node;
    00429   NodeID origin;
    00430   uint num_children;
    00431   Path *parent;
    00432 };
    00433
    00434 #endif /* LINKGRAPHJOB_H */