# 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 "../stdafx.h"
    00016 #include "../station_base.h"
    00017 #include "../cargo_type.h"
    00018 #include "../thread/thread.h"
    00019 #include "../settings_type.h"
    00020 #include "../date_func.h"
    00021 #include "linkgraph_type.h"
    00022 #include <list>
    00023 #include <vector>
    00024 #include <set>
    00025
    00026 struct SaveLoad;
    00027 class Path;
    00028
    00029 typedef std::set<Path *> PathSet;
    00030 typedef std::map<NodeID, Path *> PathViaMap;
    00031 typedef std::map<StationID, int> FlowViaMap;
    00032 typedef std::map<StationID, FlowViaMap> FlowMap;
    00033
    00039 class Node {
    00040 public:
    00041   uint supply;
    00042   uint undelivered_supply;
    00043   uint demand;
    00044   StationID station;
    00045   PathSet paths;
    00046   FlowMap flows;
    00047
    00051   ~Node() {this->Init();}
    00052
    00053   void Init(StationID st = INVALID_STATION, uint sup = 0, uint dem = 0);
    00054   void ExportFlows(CargoID cargo);
    00055
    00056 private:
    00057   void ExportNewFlows(FlowMap::iterator &it, FlowStatSet &via_set, CargoID cargo);
    00058 };
    00059
    00066 class Edge {
    00067 public:
    00068   uint distance;
    00069   uint capacity;
    00070   uint demand;
    00071   uint unsatisfied_demand;
    00072   uint flow;
    00073   NodeID next_edge;
    00074
    00075   void Init(uint distance = 0, uint capacity = 0);
    00076 };
    00077
    00084 class LinkGraphComponent {
    00085 private:
    00086   typedef std::vector<Node> NodeVector;
    00087   typedef std::vector<std::vector<Edge> > EdgeMatrix;
    00088
    00089 public:
    00090   LinkGraphComponent();
    00091
    00092   void Init(LinkGraphComponentID id);
    00093
    00100   FORCEINLINE Edge &GetEdge(NodeID from, NodeID to)
    00101   {
    00102     return this->edges[from][to];
    00103   }
    00104
    00110   FORCEINLINE Node &GetNode(NodeID num)
    00111   {
    00112     return this->nodes[num];
    00113   }
    00114
    00119   FORCEINLINE uint GetSize() const
    00120   {
    00121     return this->num_nodes;
    00122   }
    00123
    00124   void SetSize();
    00125
    00126   NodeID AddNode(Station *st);
    00127
    00128   FORCEINLINE void AddEdge(NodeID from, NodeID to, uint capacity);
    00129
    00134   FORCEINLINE LinkGraphComponentID GetIndex() const
    00135   {
    00136     return this->index;
    00137   }
    00138
    00143   FORCEINLINE CargoID GetCargo() const
    00144   {
    00145     return this->cargo;
    00146   }
    00147
    00152   FORCEINLINE const LinkGraphSettings &GetSettings() const
    00153   {
    00154     return this->settings;
    00155   }
    00156
    00162   FORCEINLINE NodeID GetFirstEdge(NodeID from)
    00163   {
    00164     return edges[from][from].next_edge;
    00165   }
    00166
    00170   FORCEINLINE void Clear()
    00171   {
    00172     this->num_nodes = 0;
    00173   }
    00174
    00175 protected:
    00176   LinkGraphSettings settings;
    00177   CargoID cargo;
    00178   uint num_nodes;
    00179   LinkGraphComponentID index;
    00180   NodeVector nodes;
    00181   EdgeMatrix edges;
    00182 };
    00183
    00188 class ComponentHandler {
    00189 public:
    00193   virtual ~ComponentHandler() {}
    00194
    00199   virtual void Run(LinkGraphComponent *component) = 0;
    00200 };
    00201
    00207 class LinkGraphJob : public LinkGraphComponent {
    00208 private:
    00209   typedef std::list<ComponentHandler *> HandlerList;
    00210
    00211 public:
    00212   LinkGraphJob() : thread(NULL) {}
    00213
    00217   ~LinkGraphJob()
    00218   {
    00219     this->Join();
    00220   }
    00221
    00222   static void RunLinkGraphJob(void *j);
    00223
    00228   static void AddHandler(ComponentHandler *handler)
    00229   {
    00230     LinkGraphJob::_handlers.push_back(handler);
    00231   }
    00232
    00233   static void ClearHandlers();
    00234
    00235   void SpawnThread();
    00236
    00237   void Join();
    00238
    00239 private:
    00240   static HandlerList _handlers;
    00241   ThreadObject *thread;
    00242
    00248   LinkGraphJob(const LinkGraphJob &other) : LinkGraphComponent(other) {NOT_REACHED();}
    00249 };
    00250
    00254 class LinkGraph : public LinkGraphJob {
    00255 public:
    00256   static const uint COMPONENTS_JOIN_TICK  = 21;
    00257   static const uint COMPONENTS_SPAWN_TICK = 58;
    00258
    00262   LinkGraph() : current_station_id(0) {}
    00263
    00264   void Init(CargoID cargo);
    00265
    00266   void NextComponent();
    00267
    00268   void Join();
    00269
    00270 private:
    00271   StationID current_station_id;
    00272
    00273   friend const SaveLoad *GetLinkGraphDesc();
    00274
    00275   void CreateComponent(Station *first);
    00276 };
    00277
    00281 class Path {
    00282 public:
    00283   Path(NodeID n, bool source = false);
    00284
    00286   FORCEINLINE NodeID GetNode() const {return this->node;}
    00287
    00289   FORCEINLINE NodeID GetOrigin() const {return this->origin;}
    00290
    00292   FORCEINLINE Path *GetParent() {return this->parent;}
    00293
    00295   FORCEINLINE uint GetCapacity() const {return this->capacity;}
    00296
    00298   FORCEINLINE int GetFreeCapacity() const {return this->free_capacity;}
    00299
    00303   FORCEINLINE int GetCapacityRatio() const {return (this->free_capacity << 4) / (this->capacity + 1);}
    00304
    00306   FORCEINLINE uint GetDistance() const {return this->distance;}
    00307
    00309   FORCEINLINE void ReduceFlow(uint f) {this->flow -= f;}
    00310
    00312   FORCEINLINE void AddFlow(uint f) {this->flow += f;}
    00313
    00315   FORCEINLINE uint GetFlow() const {return this->flow;}
    00316
    00318   FORCEINLINE uint GetNumChildren() const {return this->num_children;}
    00319
    00323   FORCEINLINE void UnFork()
    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_ */