# 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 "../station_base.h"
    00016 #include "../cargo_type.h"
    00017 #include "../thread/thread.h"
    00018 #include "../settings_type.h"
    00019 #include "../date_func.h"
    00020 #include "linkgraph_type.h"
    00021 #include <list>
    00022 #include <vector>
    00023 #include <set>
    00024
    00025 struct SaveLoad;
    00026 class Path;
    00027
    00028 typedef std::set<Path *> PathSet;
    00029 typedef std::map<NodeID, Path *> PathViaMap;
    00030 typedef std::map<StationID, int> FlowViaMap;
    00031 typedef std::map<StationID, FlowViaMap> FlowMap;
    00032
    00038 class Node {
    00039 public:
    00040   uint supply;
    00041   uint undelivered_supply;
    00042   uint demand;
    00043   StationID station;
    00044   PathSet paths;
    00045   FlowMap flows;
    00046
    00050   ~Node() {this->Init();}
    00051
    00052   void Init(StationID st = INVALID_STATION, uint sup = 0, uint dem = 0);
    00053   void ExportFlows(CargoID cargo);
    00054
    00055 private:
    00056   void ExportFlows(FlowMap::iterator &it, FlowStatMap &station_flows, CargoID cargo);
    00057 };
    00058
    00065 class Edge {
    00066 public:
    00067   uint distance;
    00068   uint capacity;
    00069   uint demand;
    00070   uint unsatisfied_demand;
    00071   uint flow;
    00072   NodeID next_edge;
    00073
    00074   void Init(uint distance = 0, uint capacity = 0);
    00075 };
    00076
    00083 class LinkGraphComponent {
    00084 private:
    00085   typedef std::vector<Node> NodeVector;
    00086   typedef std::vector<std::vector<Edge> > EdgeMatrix;
    00087
    00088 public:
    00089   LinkGraphComponent();
    00090
    00091   void Init(LinkGraphComponentID id);
    00092
    00099   inline Edge &GetEdge(NodeID from, NodeID to)
    00100   {
    00101     return this->edges[from][to];
    00102   }
    00103
    00109   inline Node &GetNode(NodeID num)
    00110   {
    00111     return this->nodes[num];
    00112   }
    00113
    00118   inline uint GetSize() const
    00119   {
    00120     return this->num_nodes;
    00121   }
    00122
    00123   void SetSize();
    00124
    00125   NodeID AddNode(Station *st);
    00126
    00127   void AddEdge(NodeID from, NodeID to, uint capacity);
    00128
    00133   inline LinkGraphComponentID GetIndex() const
    00134   {
    00135     return this->index;
    00136   }
    00137
    00142   inline CargoID GetCargo() const
    00143   {
    00144     return this->cargo;
    00145   }
    00146
    00151   inline const LinkGraphSettings &GetSettings() const
    00152   {
    00153     return this->settings;
    00154   }
    00155
    00161   inline NodeID GetFirstEdge(NodeID from) {return edges[from][from].next_edge;}
    00162
    00166   inline void Clear()
    00167   {
    00168     this->num_nodes = 0;
    00169   }
    00170
    00171 protected:
    00172   LinkGraphSettings settings;
    00173   CargoID cargo;
    00174   uint num_nodes;
    00175   LinkGraphComponentID index;
    00176   NodeVector nodes;
    00177   EdgeMatrix edges;
    00178 };
    00179
    00184 class ComponentHandler {
    00185 public:
    00189   virtual ~ComponentHandler() {}
    00190
    00196   virtual void Run(LinkGraphComponent *component) = 0;
    00197 };
    00198
    00204 class LinkGraphJob : public LinkGraphComponent {
    00205 private:
    00206   typedef std::list<ComponentHandler *> HandlerList;
    00207
    00208 public:
    00209
    00210   LinkGraphJob() : thread(NULL) {}
    00211
    00215   ~LinkGraphJob()
    00216   {
    00217     this->Join();
    00218   }
    00219
    00220   static void RunLinkGraphJob(void *j);
    00221
    00226   static void AddHandler(ComponentHandler *handler)
    00227   {
    00228     LinkGraphJob::_handlers.push_back(handler);
    00229   }
    00230
    00231   static void ClearHandlers();
    00232
    00233   void SpawnThread();
    00234
    00235   void Join();
    00236
    00237 private:
    00238   static HandlerList _handlers;
    00239   ThreadObject *thread;
    00240
    00246   LinkGraphJob(const LinkGraphJob &other) : LinkGraphComponent(other) {NOT_REACHED();}
    00247 };
    00248
    00252 class LinkGraph : public LinkGraphJob {
    00253 public:
    00254   /* Those are ticks where not much else is happening, so a small lag might go unnoticed. */
    00255   static const uint COMPONENTS_JOIN_TICK  = 21;
    00256   static const uint COMPONENTS_SPAWN_TICK = 58;
    00257
    00261   LinkGraph() : current_station_id(0) {}
    00262
    00263   void Init(CargoID cargo);
    00264
    00265   void NextComponent();
    00266
    00267   void Join();
    00268
    00269 private:
    00270   StationID current_station_id;
    00271
    00272   friend const SaveLoad *GetLinkGraphDesc();
    00273
    00274   void CreateComponent(Station *first);
    00275 };
    00276
    00280 class Path {
    00281 public:
    00282   Path(NodeID n, bool source = false);
    00283
    00285   inline NodeID GetNode() const {return this->node;}
    00286
    00288   inline NodeID GetOrigin() const {return this->origin;}
    00289
    00291   inline Path *GetParent() {return this->parent;}
    00292
    00294   inline uint GetCapacity() const {return this->capacity;}
    00295
    00297   inline int GetFreeCapacity() const {return this->free_capacity;}
    00298
    00303   inline int GetCapacityRatio() const {return (this->free_capacity << 4) / (this->capacity + 1);}
    00304
    00306   inline uint GetDistance() const {return this->distance;}
    00307
    00309   inline void ReduceFlow(uint f) {this->flow -= f;}
    00310
    00312   inline void AddFlow(uint f) {this->flow += f;}
    00313
    00315   inline uint GetFlow() const {return this->flow;}
    00316
    00318   inline uint GetNumChildren() const {return this->num_children;}
    00319
    00323   inline void Detach()
    00324   {
    00325     if (this->parent != NULL) {
    00326       this->parent->num_children--;
    00327       this->parent = NULL;
    00328     }
    00329   }
    00330
    00331   uint AddFlow(uint f, LinkGraphComponent *graph, bool only_positive);
    00332   void Fork(Path *base, uint cap, int free_cap, uint dist);
    00333
    00334 protected:
    00335   uint distance;
    00336   uint capacity;
    00337   int free_capacity;
    00338   uint flow;
    00339   NodeID node;
    00340   NodeID origin;
    00341   uint num_children;
    00342   Path *parent;
    00343 };
    00344
    00345 void InitializeLinkGraphs();
    00346 extern LinkGraph _link_graphs[NUM_CARGO];
    00347
    00348 #endif /* LINKGRAPH_H_ */