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 */