00001
00002
00003
00004
00005
00006
00007
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, 0xFFFFFF> 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 public:
00068
00073 class Edge : public LinkGraph::ConstEdge {
00074 private:
00075 EdgeAnnotation &anno;
00076 public:
00082 Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
00083 LinkGraph::ConstEdge(edge), anno(anno) {}
00084
00089 uint Demand() const { return this->anno.demand; }
00090
00095 uint UnsatisfiedDemand() const { return this->anno.unsatisfied_demand; }
00096
00101 uint Flow() const { return this->anno.flow; }
00102
00107 void AddFlow(uint flow) { this->anno.flow += flow; }
00108
00113 void RemoveFlow(uint flow)
00114 {
00115 assert(flow <= this->anno.flow);
00116 this->anno.flow -= flow;
00117 }
00118
00123 void AddDemand(uint demand)
00124 {
00125 this->anno.demand += demand;
00126 this->anno.unsatisfied_demand += demand;
00127 }
00128
00133 void SatisfyDemand(uint demand)
00134 {
00135 assert(demand <= this->anno.unsatisfied_demand);
00136 this->anno.unsatisfied_demand -= demand;
00137 }
00138 };
00139
00143 class EdgeIterator : public LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator> {
00144 EdgeAnnotation *base_anno;
00145 public:
00152 EdgeIterator(const LinkGraph::BaseEdge *base, EdgeAnnotation *base_anno, NodeID current) :
00153 LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, current),
00154 base_anno(base_anno) {}
00155
00161 SmallPair<NodeID, Edge> operator*() const
00162 {
00163 return SmallPair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
00164 }
00165
00171 FakePointer operator->() const {
00172 return FakePointer(this->operator*());
00173 }
00174 };
00175
00180 class Node : public LinkGraph::ConstNode {
00181 private:
00182 NodeAnnotation &node_anno;
00183 EdgeAnnotation *edge_annos;
00184 public:
00185
00191 Node (LinkGraphJob *lgj, NodeID node) :
00192 LinkGraph::ConstNode(&lgj->link_graph, node),
00193 node_anno(lgj->nodes[node]), edge_annos(lgj->edges[node])
00194 {}
00195
00202 Edge operator[](NodeID to) const { return Edge(this->edges[to], this->edge_annos[to]); }
00203
00209 EdgeIterator Begin() const { return EdgeIterator(this->edges, this->edge_annos, index); }
00210
00216 EdgeIterator End() const { return EdgeIterator(this->edges, this->edge_annos, INVALID_NODE); }
00217
00222 uint UndeliveredSupply() const { return this->node_anno.undelivered_supply; }
00223
00228 FlowStatMap &Flows() { return this->node_anno.flows; }
00229
00234 const FlowStatMap &Flows() const { return this->node_anno.flows; }
00235
00241 PathList &Paths() { return this->node_anno.paths; }
00242
00247 const PathList &Paths() const { return this->node_anno.paths; }
00248
00254 void DeliverSupply(NodeID to, uint amount)
00255 {
00256 this->node_anno.undelivered_supply -= amount;
00257 (*this)[to].AddDemand(amount);
00258 }
00259 };
00260
00265 LinkGraphJob() : settings(_settings_game.linkgraph), thread(NULL),
00266 join_date(INVALID_DATE) {}
00267
00268 LinkGraphJob(const LinkGraph &orig);
00269 ~LinkGraphJob();
00270
00271 void Init();
00272
00277 inline bool IsFinished() const { return this->join_date <= _date; }
00278
00283 inline Date JoinDate() const { return join_date; }
00284
00289 inline void ShiftJoinDate(int interval) { this->join_date += interval; }
00290
00295 inline const LinkGraphSettings &Settings() const { return this->settings; }
00296
00302 inline Node operator[](NodeID num) { return Node(this, num); }
00303
00308 inline uint Size() const { return this->link_graph.Size(); }
00309
00314 inline CargoID Cargo() const { return this->link_graph.Cargo(); }
00315
00320 inline Date LastCompression() const { return this->link_graph.LastCompression(); }
00321
00326 inline LinkGraphID LinkGraphIndex() const { return this->link_graph.index; }
00327
00332 inline const LinkGraph &Graph() const { return this->link_graph; }
00333 };
00334
00335 #define FOR_ALL_LINK_GRAPH_JOBS(var) FOR_ALL_ITEMS_FROM(LinkGraphJob, link_graph_job_index, var, 0)
00336
00340 class Path {
00341 public:
00342 Path(NodeID n, bool source = false);
00343
00345 inline NodeID GetNode() const { return this->node; }
00346
00348 inline NodeID GetOrigin() const { return this->origin; }
00349
00351 inline Path *GetParent() { return this->parent; }
00352
00354 inline uint GetCapacity() const { return this->capacity; }
00355
00357 inline int GetFreeCapacity() const { return this->free_capacity; }
00358
00366 inline static int GetCapacityRatio(int free, uint total)
00367 {
00368 return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / max(total, 1U);
00369 }
00370
00375 inline int GetCapacityRatio() const
00376 {
00377 return Path::GetCapacityRatio(this->free_capacity, this->capacity);
00378 }
00379
00381 inline uint GetDistance() const { return this->distance; }
00382
00384 inline void ReduceFlow(uint f) { this->flow -= f; }
00385
00387 inline void AddFlow(uint f) { this->flow += f; }
00388
00390 inline uint GetFlow() const { return this->flow; }
00391
00393 inline uint GetNumChildren() const { return this->num_children; }
00394
00398 inline void Detach()
00399 {
00400 if (this->parent != NULL) {
00401 this->parent->num_children--;
00402 this->parent = NULL;
00403 }
00404 }
00405
00406 uint AddFlow(uint f, LinkGraphJob &job, uint max_saturation);
00407 void Fork(Path *base, uint cap, int free_cap, uint dist);
00408
00409 protected:
00410
00414 enum PathCapacityBoundaries {
00415 PATH_CAP_MULTIPLIER = 16,
00416 PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER,
00417 PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER
00418 };
00419
00420 uint distance;
00421 uint capacity;
00422 int free_capacity;
00423 uint flow;
00424 NodeID node;
00425 NodeID origin;
00426 uint num_children;
00427 Path *parent;
00428 };
00429
00430 #endif