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/>.
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"
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
;
27 * Class for calculation jobs to be run on link graphs.
29 class LinkGraphJob
: public LinkGraphJobPool::PoolItem
<&_link_graph_job_pool
>{
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.
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) {}
50 * Get the total flow on the edge.
53 uint
Flow() const { return this->flow
; }
57 * @param flow Flow to be added.
59 void AddFlow(uint flow
) { this->flow
+= flow
; }
63 * @param flow Flow to be removed.
65 void RemoveFlow(uint flow
)
67 assert(flow
<= this->flow
);
71 friend inline bool operator <(NodeID dest
, const EdgeAnnotation
&rhs
)
73 return dest
< rhs
.base
.dest_node
;
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
);
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());
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());
122 * Get the transport demand between end the points of the edge.
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
;
157 typedef std::vector
<NodeAnnotation
> NodeAnnotationVector
;
159 friend SaveLoadTable
GetLinkGraphJobDesc();
160 friend class LinkGraphSchedule
;
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
);
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
);
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
); }
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.
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.
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.
245 inline NodeID
Size() const { return this->link_graph
.Size(); }
248 * Get the cargo of the underlying link graph.
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".
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.
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
);
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 */