linkgraph.h

Go to the documentation of this file.
00001 /* $Id$ */
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 LINKGRAPH_H
00013 #define LINKGRAPH_H
00014 
00015 #include "../core/pool_type.hpp"
00016 #include "../core/smallvec_type.hpp"
00017 #include "../core/smallmatrix_type.hpp"
00018 #include "../station_base.h"
00019 #include "../cargo_type.h"
00020 #include "../thread/thread.h"
00021 #include "../settings_type.h"
00022 #include "../date_func.h"
00023 #include "linkgraph_type.h"
00024 #include <list>
00025 #include <set>
00026 
00027 struct SaveLoad;
00028 class LinkGraph;
00029 class LinkGraphJob;
00030 class Path;
00031 
00032 typedef std::set<Path *> PathSet;
00033 typedef std::map<NodeID, Path *> PathViaMap;
00034 
00035 class GraphItem {
00036 protected:
00037   uint Monthly(uint base, uint last_compression) const
00038   {
00039     return base * 30 / (_date - last_compression + 1);
00040   }
00041 };
00042 
00048 class Node : public GraphItem{
00049 public:
00050   uint supply;             
00051   uint demand;             
00052   StationID station;       
00053   Date last_update;        
00054 
00058   ~Node() { this->Init(); }
00059 
00060   void Init(StationID st = INVALID_STATION, uint demand = 0);
00061 
00062   uint MonthlySupply(Date last_compression) const
00063   {
00064     return this->Monthly(this->supply, last_compression);
00065   }
00066 };
00067 
00074 class Edge : public GraphItem {
00075 public:
00076   static const uint MIN_DISTANCE = 48; 
00077 
00078   uint distance;           
00079   uint capacity;           
00080   uint usage;              
00081   Date last_update;        
00082   NodeID next_edge;        
00083 
00084   void Init(uint distance = 0);
00085 
00086   uint MonthlyCapacity(Date last_compression) const
00087   {
00088     return this->Monthly(this->capacity, last_compression);
00089   }
00090 
00091   uint MonthlyUsage(Date last_compression) const
00092   {
00093     return this->Monthly(this->usage, last_compression);
00094   }
00095 };
00096 
00101 class ComponentHandler {
00102 public:
00106   virtual ~ComponentHandler() {}
00107 
00113   virtual void Run(LinkGraphJob *job) = 0;
00114 };
00115 
00120 typedef Pool<LinkGraph, LinkGraphID, 32, 0xFFFFFF> LinkGraphPool;
00122 extern LinkGraphPool _link_graph_pool;
00123 
00130 class LinkGraph : public LinkGraphPool::PoolItem<&_link_graph_pool> {
00131 private:
00132   typedef SmallVector<Node, 16> NodeVector;
00133   typedef SmallMatrix<Edge> EdgeMatrix;
00134 
00135   friend const SaveLoad *GetLinkGraphDesc();
00136   friend const SaveLoad *GetLinkGraphJobDesc();
00137 
00138 public:
00139   static const uint COMPRESSION_TICK = 58;
00140 
00142   LinkGraph() : cargo(INVALID_CARGO), num_nodes(0), last_compression(0) {}
00143   LinkGraph(CargoID cargo) : cargo(cargo), num_nodes(0), last_compression(_date) {}
00144 
00145   void Compress();
00146   void Merge(LinkGraph *other);
00147 
00148   /* Splitting link graphs is intentionally not implemented.
00149    * The overhead in determining connectedness would probably outweigh the
00150    * benefit of having to deal with smaller graphs. In real world examples
00151    * networks generally grow. Only rarely a network is permanently split.
00152    * Reacting to temporary splits here would obviously create performance
00153    * problems and detecting the temporary or permanent nature of splits isn't
00154    * trivial. */
00155 
00162   inline Edge &GetEdge(NodeID from, NodeID to)
00163   {
00164     return this->edges[from][to];
00165   }
00166 
00173   inline const Edge &GetEdge(NodeID from, NodeID to) const
00174   {
00175     return this->edges[from][to];
00176   }
00177 
00183   inline Node &GetNode(NodeID num)
00184   {
00185     return this->nodes[num];
00186   }
00187 
00193   inline const Node &GetNode(NodeID num) const
00194   {
00195     return this->nodes[num];
00196   }
00197 
00202   inline uint GetSize() const
00203   {
00204     return this->num_nodes;
00205   }
00206 
00211   inline Date GetLastCompression() const
00212   {
00213     return this->last_compression;
00214   }
00215 
00220   inline CargoID GetCargo() const
00221   {
00222     return this->cargo;
00223   }
00224 
00225   void SetSize();
00226 
00227   NodeID AddNode(const Station *st);
00228   void RemoveNode(NodeID id);
00229 
00230   void AddEdge(NodeID from, NodeID to, uint capacity);
00231   void UpdateEdge(NodeID from, NodeID to, uint capacity, uint usage);
00232   void RemoveEdge(NodeID from, NodeID to);
00233 
00239   inline NodeID GetFirstEdge(NodeID from) const { return edges[from][from].next_edge; }
00240 
00247   inline NodeID GetNextEdge(NodeID from, NodeID to) const { return edges[from][to].next_edge; }
00248 
00249 protected:
00250   void ResizeNodes();
00251 
00252   CargoID cargo;              
00253   uint16 num_nodes;             
00254   Date last_compression;      
00255   NodeVector nodes;           
00256   EdgeMatrix edges;           
00257 };
00258 
00259 #define FOR_ALL_LINK_GRAPHS(var) FOR_ALL_ITEMS_FROM(LinkGraph, link_graph_index, var, 0)
00260 
00262 typedef Pool<LinkGraphJob, LinkGraphJobID, 32, 0xFFFFFF> LinkGraphJobPool;
00264 extern LinkGraphJobPool _link_graph_job_pool;
00265 
00266 class EdgeAnnotation {
00267 public:
00268   uint demand;             
00269   uint unsatisfied_demand; 
00270   uint flow;               
00271 };
00272 
00273 class NodeAnnotation {
00274 public:
00275   uint undelivered_supply; 
00276   PathSet paths;           
00277   FlowStatMap flows;       
00278 };
00279 
00280 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
00281 private:
00282   typedef SmallVector<NodeAnnotation, 16> NodeAnnotationVector;
00283   typedef SmallMatrix<EdgeAnnotation> EdgeAnnotationMatrix;
00284 
00285   friend const SaveLoad *GetLinkGraphJobDesc();
00286   friend class LinkGraphSchedule;
00287 
00288 protected:
00289   LinkGraph link_graph;
00290   LinkGraphSettings settings; 
00291   ThreadObject *thread;       
00292   Date join_date;             
00293   NodeAnnotationVector nodes; 
00294   EdgeAnnotationMatrix edges; 
00295 
00296   void SpawnThread();
00297   void JoinThread();
00298 
00299 public:
00301   LinkGraphJob() : thread(NULL), join_date(INVALID_DATE) {}
00302   LinkGraphJob(const LinkGraph &orig);
00303   ~LinkGraphJob();
00304 
00305   inline bool IsFinished() const
00306   {
00307     return this->join_date < _date;
00308   }
00309 
00310   inline Date JoinDate() const { return join_date; }
00311 
00316   inline const LinkGraphSettings &Settings() const
00317   {
00318     return this->settings;
00319   }
00320 
00324   inline LinkGraph &Graph()
00325   {
00326     return this->link_graph;
00327   }
00328 
00329   inline EdgeAnnotationMatrix &Edges()
00330   {
00331     return this->edges;
00332   }
00333 
00334   inline NodeAnnotationVector &Nodes()
00335   {
00336     return this->nodes;
00337   }
00338 
00345   inline EdgeAnnotation &GetEdge(NodeID from, NodeID to)
00346   {
00347     return this->edges[from][to];
00348   }
00349 
00355   inline NodeAnnotation &GetNode(NodeID num)
00356   {
00357     return this->nodes[num];
00358   }
00359 };
00360 
00361 #define FOR_ALL_LINK_GRAPH_JOBS(var) FOR_ALL_ITEMS_FROM(LinkGraphJob, link_graph_job_index, var, 0)
00362 
00363 class LinkGraphSchedule {
00364 private:
00365   LinkGraphSchedule();
00366   ~LinkGraphSchedule();
00367   typedef std::list<LinkGraph *> GraphList;
00368   typedef std::list<LinkGraphJob *> JobList;
00369   friend const SaveLoad *GetLinkGraphScheduleDesc();
00370 
00371 protected:
00372   ComponentHandler *handlers[6]; 
00373   GraphList schedule;            
00374   JobList running;               
00375 
00376 public:
00377   /* This is a tick where not much else is happening, so a small lag might go unnoticed. */
00378   static const uint SPAWN_JOIN_TICK = 21; 
00379 
00380   static LinkGraphSchedule *Instance();
00381   static void Run(void *j);
00382   static void Clear();
00383   void SpawnNext();
00384   void JoinNext();
00385   void Queue(LinkGraph *lg)
00386   {
00387     assert(LinkGraph::Get(lg->index) == lg);
00388     this->schedule.push_back(lg);
00389   }
00390   void Unqueue(LinkGraph *lg) { this->schedule.remove(lg); }
00391   void SpawnAll();
00392 };
00393 
00397 class Path {
00398 public:
00399   Path(NodeID n, bool source = false);
00400 
00402   inline NodeID GetNode() const { return this->node; }
00403 
00405   inline NodeID GetOrigin() const { return this->origin; }
00406 
00408   inline Path *GetParent() { return this->parent; }
00409 
00411   inline uint GetCapacity() const { return this->capacity; }
00412 
00414   inline int GetFreeCapacity() const { return this->free_capacity; }
00415 
00423   inline static int GetCapacityRatio(int free, int total)
00424   {
00425     return (free << 4) / (total + 1);
00426   }
00427 
00432   inline int GetCapacityRatio() const
00433   {
00434     return Path::GetCapacityRatio(this->free_capacity, this->capacity);
00435   }
00436 
00438   inline uint GetDistance() const { return this->distance; }
00439 
00441   inline void ReduceFlow(uint f) { this->flow -= f; }
00442 
00444   inline void AddFlow(uint f) { this->flow += f; }
00445 
00447   inline uint GetFlow() const { return this->flow; }
00448 
00450   inline uint GetNumChildren() const { return this->num_children; }
00451 
00455   inline void Detach()
00456   {
00457     if (this->parent != NULL) {
00458       this->parent->num_children--;
00459       this->parent = NULL;
00460     }
00461   }
00462 
00463   uint AddFlow(uint f, LinkGraphJob *job, uint max_saturation);
00464   void Fork(Path *base, uint cap, int free_cap, uint dist);
00465 
00466 protected:
00467   uint distance;     
00468   uint capacity;     
00469   int free_capacity; 
00470   uint flow;         
00471   NodeID node;       
00472   NodeID origin;     
00473   uint num_children; 
00474   Path *parent;      
00475 };
00476 
00477 #endif /* LINKGRAPH_H */