Update: Translations from eints
[openttd-github.git] / src / linkgraph / linkgraphjob.h
blobb84eaf64174b6d715eb58ac0fcf10170918173e3
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
8 /** @file linkgraphjob.h Declaration of link graph job classes used for cargo distribution. */
10 #ifndef LINKGRAPHJOB_H
11 #define LINKGRAPHJOB_H
13 #include "../thread.h"
14 #include "linkgraph.h"
15 #include <atomic>
17 class LinkGraphJob;
18 class Path;
19 typedef std::list<Path *> PathList;
21 /** Type of the pool for link graph jobs. */
22 typedef Pool<LinkGraphJob, LinkGraphJobID, 32, 0xFFFF> LinkGraphJobPool;
23 /** The actual pool with link graph jobs. */
24 extern LinkGraphJobPool _link_graph_job_pool;
26 /**
27 * Class for calculation jobs to be run on link graphs.
29 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
30 public:
31 /**
32 * Demand between two nodes.
34 struct DemandAnnotation {
35 uint demand; ///< Transport demand between the nodes.
36 uint unsatisfied_demand; ///< Demand over this edge that hasn't been satisfied yet.
39 /**
40 * Annotation for a link graph edge.
42 struct EdgeAnnotation {
43 const LinkGraph::BaseEdge &base; ///< Reference to the edge that is annotated.
45 uint flow; ///< Planned flow over this edge.
47 EdgeAnnotation(const LinkGraph::BaseEdge &base) : base(base), flow(0) {}
49 /**
50 * Get the total flow on the edge.
51 * @return Flow.
53 uint Flow() const { return this->flow; }
55 /**
56 * Add some flow.
57 * @param flow Flow to be added.
59 void AddFlow(uint flow) { this->flow += flow; }
61 /**
62 * Remove some flow.
63 * @param flow Flow to be removed.
65 void RemoveFlow(uint flow)
67 assert(flow <= this->flow);
68 this->flow -= flow;
71 friend inline bool operator <(NodeID dest, const EdgeAnnotation &rhs)
73 return dest < rhs.base.dest_node;
77 /**
78 * Annotation for a link graph node.
80 struct NodeAnnotation {
81 const LinkGraph::BaseNode &base; ///< Reference to the node that is annotated.
83 uint undelivered_supply; ///< Amount of supply that hasn't been distributed yet.
84 PathList paths; ///< Paths through this node, sorted so that those with flow == 0 are in the back.
85 FlowStatMap flows; ///< Planned flows to other nodes.
87 std::vector<EdgeAnnotation> edges; ///< Annotations for all edges originating at this node.
88 std::vector<DemandAnnotation> demands; ///< Annotations for the demand to all other nodes.
90 NodeAnnotation(const LinkGraph::BaseNode &node, size_t size) : base(node), undelivered_supply(node.supply), paths(), flows()
92 this->edges.reserve(node.edges.size());
93 for (auto &e : node.edges) this->edges.emplace_back(e);
94 this->demands.resize(size);
97 /**
98 * Retrieve an edge starting at this node.
99 * @param to Remote end of the edge.
100 * @return Edge between this node and "to".
102 EdgeAnnotation &operator[](NodeID to)
104 auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
105 assert(it != this->edges.end());
106 return *it;
110 * Retrieve an edge starting at this node.
111 * @param to Remote end of the edge.
112 * @return Edge between this node and "to".
114 const EdgeAnnotation &operator[](NodeID to) const
116 auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
117 assert(it != this->edges.end());
118 return *it;
122 * Get the transport demand between end the points of the edge.
123 * @return Demand.
125 uint DemandTo(NodeID to) const { return this->demands[to].demand; }
128 * Get the transport demand that hasn't been satisfied by flows, yet.
129 * @return Unsatisfied demand.
131 uint UnsatisfiedDemandTo(NodeID to) const { return this->demands[to].unsatisfied_demand; }
134 * Satisfy some demand.
135 * @param demand Demand to be satisfied.
137 void SatisfyDemandTo(NodeID to, uint demand)
139 assert(demand <= this->demands[to].unsatisfied_demand);
140 this->demands[to].unsatisfied_demand -= demand;
144 * Deliver some supply, adding demand to the respective edge.
145 * @param to Destination for supply.
146 * @param amount Amount of supply to be delivered.
148 void DeliverSupply(NodeID to, uint amount)
150 this->undelivered_supply -= amount;
151 this->demands[to].demand += amount;
152 this->demands[to].unsatisfied_demand += amount;
156 private:
157 typedef std::vector<NodeAnnotation> NodeAnnotationVector;
159 friend SaveLoadTable GetLinkGraphJobDesc();
160 friend class LinkGraphSchedule;
162 protected:
163 const LinkGraph link_graph; ///< Link graph to by analyzed. Is copied when job is started and mustn't be modified later.
164 const LinkGraphSettings settings; ///< Copy of _settings_game.linkgraph at spawn time.
165 std::thread thread; ///< Thread the job is running in or a default-constructed thread if it's running in the main thread.
166 TimerGameEconomy::Date join_date; ///< Date when the job is to be joined.
167 NodeAnnotationVector nodes; ///< Extra node data necessary for link graph calculation.
168 std::atomic<bool> job_completed; ///< Is the job still running. This is accessed by multiple threads and reads may be stale.
169 std::atomic<bool> job_aborted; ///< Has the job been aborted. This is accessed by multiple threads and reads may be stale.
171 void EraseFlows(NodeID from);
172 void JoinThread();
173 void SpawnThread();
175 public:
177 * Bare constructor, only for save/load. link_graph, join_date and actually
178 * settings have to be brutally const-casted in order to populate them.
180 LinkGraphJob() : settings(_settings_game.linkgraph),
181 join_date(EconomyTime::INVALID_DATE), job_completed(false), job_aborted(false) {}
183 LinkGraphJob(const LinkGraph &orig);
184 ~LinkGraphJob();
186 void Init();
189 * Check if job has actually finished.
190 * This is allowed to spuriously return an incorrect value.
191 * @return True if job has actually finished.
193 inline bool IsJobCompleted() const { return this->job_completed.load(std::memory_order_acquire); }
196 * Check if job has been aborted.
197 * This is allowed to spuriously return false incorrectly, but is not allowed to incorrectly return true.
198 * @return True if job has been aborted.
200 inline bool IsJobAborted() const { return this->job_aborted.load(std::memory_order_acquire); }
203 * Abort job.
204 * The job may exit early at the next available opportunity.
205 * After this method has been called the state of the job is undefined, and the only valid operation
206 * is to join the thread and discard the job data.
208 inline void AbortJob() { this->job_aborted.store(true, std::memory_order_release); }
211 * Check if job is supposed to be finished.
212 * @return True if job should be finished by now, false if not.
214 inline bool IsScheduledToBeJoined() const { return this->join_date <= TimerGameEconomy::date; }
217 * Get the date when the job should be finished.
218 * @return Join date.
220 inline TimerGameEconomy::Date JoinDate() const { return join_date; }
223 * Change the join date on date cheating.
224 * @param interval Number of days to add.
226 inline void ShiftJoinDate(TimerGameEconomy::Date interval) { this->join_date += interval; }
229 * Get the link graph settings for this component.
230 * @return Settings.
232 inline const LinkGraphSettings &Settings() const { return this->settings; }
235 * Get a node abstraction with the specified id.
236 * @param num ID of the node.
237 * @return the Requested node.
239 inline NodeAnnotation &operator[](NodeID num) { return this->nodes[num]; }
242 * Get the size of the underlying link graph.
243 * @return Size.
245 inline NodeID Size() const { return this->link_graph.Size(); }
248 * Get the cargo of the underlying link graph.
249 * @return Cargo.
251 inline CargoID Cargo() const { return this->link_graph.Cargo(); }
254 * Get the date when the underlying link graph was last compressed.
255 * @return Compression date.
257 inline TimerGameEconomy::Date LastCompression() const { return this->link_graph.LastCompression(); }
260 * Get the ID of the underlying link graph.
261 * @return Link graph ID.
263 inline LinkGraphID LinkGraphIndex() const { return this->link_graph.index; }
266 * Get a reference to the underlying link graph. Only use this for save/load.
267 * @return Link graph.
269 inline const LinkGraph &Graph() const { return this->link_graph; }
273 * A leg of a path in the link graph. Paths can form trees by being "forked".
275 class Path {
276 public:
277 static Path *invalid_path;
279 Path(NodeID n, bool source = false);
280 virtual ~Path() = default;
282 /** Get the node this leg passes. */
283 inline NodeID GetNode() const { return this->node; }
285 /** Get the overall origin of the path. */
286 inline NodeID GetOrigin() const { return this->origin; }
288 /** Get the parent leg of this one. */
289 inline Path *GetParent() { return this->parent; }
291 /** Get the overall capacity of the path. */
292 inline uint GetCapacity() const { return this->capacity; }
294 /** Get the free capacity of the path. */
295 inline int GetFreeCapacity() const { return this->free_capacity; }
298 * Get ratio of free * 16 (so that we get fewer 0) /
299 * max(total capacity, 1) (so that we don't divide by 0).
300 * @param free Free capacity.
301 * @param total Total capacity.
302 * @return free * 16 / max(total, 1).
304 inline static int GetCapacityRatio(int free, uint total)
306 return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / std::max(total, 1U);
310 * Get capacity ratio of this path.
311 * @return free capacity * 16 / (total capacity + 1).
313 inline int GetCapacityRatio() const
315 return Path::GetCapacityRatio(this->free_capacity, this->capacity);
318 /** Get the overall distance of the path. */
319 inline uint GetDistance() const { return this->distance; }
321 /** Reduce the flow on this leg only by the specified amount. */
322 inline void ReduceFlow(uint f) { this->flow -= f; }
324 /** Increase the flow on this leg only by the specified amount. */
325 inline void AddFlow(uint f) { this->flow += f; }
327 /** Get the flow on this leg. */
328 inline uint GetFlow() const { return this->flow; }
330 /** Get the number of "forked off" child legs of this one. */
331 inline uint GetNumChildren() const { return this->num_children; }
334 * Detach this path from its parent.
336 inline void Detach()
338 if (this->parent != nullptr) {
339 this->parent->num_children--;
340 this->parent = nullptr;
344 uint AddFlow(uint f, LinkGraphJob &job, uint max_saturation);
345 void Fork(Path *base, uint cap, int free_cap, uint dist);
347 protected:
350 * Some boundaries to clamp against in order to avoid integer overflows.
352 static constexpr int PATH_CAP_MULTIPLIER = 16;
353 static constexpr int PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER;
354 static constexpr int PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER;
356 uint distance; ///< Sum(distance of all legs up to this one).
357 uint capacity; ///< This capacity is min(capacity) fom all edges.
358 int free_capacity; ///< This capacity is min(edge.capacity - edge.flow) for the current run of Dijkstra.
359 uint flow; ///< Flow the current run of the mcf solver assigns.
360 NodeID node; ///< Link graph node this leg passes.
361 NodeID origin; ///< Link graph node this path originates from.
362 uint num_children; ///< Number of child legs that have been forked from this path.
363 Path *parent; ///< Parent leg of this one.
366 #endif /* LINKGRAPHJOB_H */