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, 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