Merge remote-tracking branch 'upstream/master'
This commit is contained in:
22
src/linkgraph/CMakeLists.txt
Normal file
22
src/linkgraph/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
add_files(
|
||||
demands.cpp
|
||||
demands.h
|
||||
flowmapper.cpp
|
||||
flowmapper.h
|
||||
init.h
|
||||
linkgraph.cpp
|
||||
linkgraph.h
|
||||
linkgraph_base.h
|
||||
linkgraph_gui.cpp
|
||||
linkgraph_gui.h
|
||||
linkgraph_type.h
|
||||
linkgraphjob.cpp
|
||||
linkgraphjob.h
|
||||
linkgraphjob_base.h
|
||||
linkgraphschedule.cpp
|
||||
linkgraphschedule.h
|
||||
mcf.cpp
|
||||
mcf.h
|
||||
refresh.cpp
|
||||
refresh.h
|
||||
)
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
*/
|
||||
inline void SetDemandPerNode(uint num_demands)
|
||||
{
|
||||
this->demand_per_node = max(this->supply_sum / num_demands, 1U);
|
||||
this->demand_per_node = std::max(this->supply_sum / num_demands, 1U);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
*/
|
||||
inline uint EffectiveSupply(const Node &from, const Node &to)
|
||||
{
|
||||
return max(from.Supply() * max(1U, to.Supply()) * this->mod_size / 100 / this->demand_per_node, 1U);
|
||||
return std::max(from.Supply() * std::max(1U, to.Supply()) * this->mod_size / 100 / this->demand_per_node, 1U);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,7 +134,7 @@ void SymmetricScaler::SetDemands(LinkGraphJob &job, NodeID from_id, NodeID to_id
|
||||
uint undelivered = job[to_id].UndeliveredSupply();
|
||||
if (demand_back > undelivered) {
|
||||
demand_back = undelivered;
|
||||
demand_forw = max(1U, demand_back * 100 / this->mod_size);
|
||||
demand_forw = std::max(1U, demand_back * 100 / this->mod_size);
|
||||
}
|
||||
this->Scaler::SetDemands(job, to_id, from_id, demand_back);
|
||||
}
|
||||
@@ -230,7 +230,7 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
||||
demand_forw = 1;
|
||||
}
|
||||
|
||||
demand_forw = min(demand_forw, job[from_id].UndeliveredSupply());
|
||||
demand_forw = std::min(demand_forw, job[from_id].UndeliveredSupply());
|
||||
|
||||
scaler.SetDemands(job, from_id, to_id, demand_forw);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ void LinkGraph::Compress()
|
||||
for (NodeID node2 = 0; node2 < this->Size(); ++node2) {
|
||||
BaseEdge &edge = this->edges[node1][node2];
|
||||
if (edge.capacity > 0) {
|
||||
edge.capacity = max(1U, edge.capacity / 2);
|
||||
edge.capacity = std::max(1U, edge.capacity / 2);
|
||||
edge.usage /= 2;
|
||||
}
|
||||
}
|
||||
@@ -163,8 +163,7 @@ NodeID LinkGraph::AddNode(const Station *st)
|
||||
this->nodes.emplace_back();
|
||||
/* Avoid reducing the height of the matrix as that is expensive and we
|
||||
* most likely will increase it again later which is again expensive. */
|
||||
this->edges.Resize(new_node + 1U,
|
||||
max(new_node + 1U, this->edges.Height()));
|
||||
this->edges.Resize(new_node + 1U, std::max(new_node + 1U, this->edges.Height()));
|
||||
|
||||
this->nodes[new_node].Init(st->xy, st->index,
|
||||
HasBit(good.status, GoodsEntry::GES_ACCEPTANCE));
|
||||
@@ -266,8 +265,8 @@ void LinkGraph::Edge::Update(uint capacity, uint usage, EdgeUpdateMode mode)
|
||||
this->edge.capacity += capacity;
|
||||
this->edge.usage += usage;
|
||||
} else if (mode & EUM_REFRESH) {
|
||||
this->edge.capacity = max(this->edge.capacity, capacity);
|
||||
this->edge.usage = max(this->edge.usage, usage);
|
||||
this->edge.capacity = std::max(this->edge.capacity, capacity);
|
||||
this->edge.usage = std::max(this->edge.usage, usage);
|
||||
}
|
||||
if (mode & EUM_UNRESTRICTED) this->edge.last_unrestricted_update = _date;
|
||||
if (mode & EUM_RESTRICTED) this->edge.last_restricted_update = _date;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "../cargotype.h"
|
||||
#include "../date_func.h"
|
||||
#include "linkgraph_type.h"
|
||||
#include <utility>
|
||||
|
||||
struct SaveLoad;
|
||||
class LinkGraph;
|
||||
@@ -112,7 +113,7 @@ public:
|
||||
* Get the date of the last update to any part of the edge's capacity.
|
||||
* @return Last update.
|
||||
*/
|
||||
Date LastUpdate() const { return max(this->edge.last_unrestricted_update, this->edge.last_restricted_update); }
|
||||
Date LastUpdate() const { return std::max(this->edge.last_unrestricted_update, this->edge.last_restricted_update); }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -188,20 +189,20 @@ public:
|
||||
* to return something that implements operator->, but isn't a pointer
|
||||
* from operator->. A fake pointer.
|
||||
*/
|
||||
class FakePointer : public SmallPair<NodeID, Tedge_wrapper> {
|
||||
class FakePointer : public std::pair<NodeID, Tedge_wrapper> {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a fake pointer from a pair of NodeID and edge.
|
||||
* @param pair Pair to be "pointed" to (in fact shallow-copied).
|
||||
*/
|
||||
FakePointer(const SmallPair<NodeID, Tedge_wrapper> &pair) : SmallPair<NodeID, Tedge_wrapper>(pair) {}
|
||||
FakePointer(const std::pair<NodeID, Tedge_wrapper> &pair) : std::pair<NodeID, Tedge_wrapper>(pair) {}
|
||||
|
||||
/**
|
||||
* Retrieve the pair by operator->.
|
||||
* @return Pair being "pointed" to.
|
||||
*/
|
||||
SmallPair<NodeID, Tedge_wrapper> *operator->() { return this; }
|
||||
std::pair<NodeID, Tedge_wrapper> *operator->() { return this; }
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -266,9 +267,9 @@ public:
|
||||
* Dereference with operator*.
|
||||
* @return Pair of current target NodeID and edge object.
|
||||
*/
|
||||
SmallPair<NodeID, Tedge_wrapper> operator*() const
|
||||
std::pair<NodeID, Tedge_wrapper> operator*() const
|
||||
{
|
||||
return SmallPair<NodeID, Tedge_wrapper>(this->current, Tedge_wrapper(this->base[this->current]));
|
||||
return std::pair<NodeID, Tedge_wrapper>(this->current, Tedge_wrapper(this->base[this->current]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,7 +453,7 @@ public:
|
||||
*/
|
||||
inline static uint Scale(uint val, uint target_age, uint orig_age)
|
||||
{
|
||||
return val > 0 ? max(1U, val * target_age / orig_age) : 0;
|
||||
return val > 0 ? std::max(1U, val * target_age / orig_age) : 0;
|
||||
}
|
||||
|
||||
/** Bare constructor, only for save/load. */
|
||||
|
||||
@@ -224,7 +224,7 @@ void LinkGraphOverlay::AddLinks(const Station *from, const Station *to)
|
||||
{
|
||||
/* multiply the numbers by 32 in order to avoid comparing to 0 too often. */
|
||||
if (cargo.capacity == 0 ||
|
||||
max(cargo.usage, cargo.planned) * 32 / (cargo.capacity + 1) < max(new_usg, new_plan) * 32 / (new_cap + 1)) {
|
||||
std::max(cargo.usage, cargo.planned) * 32 / (cargo.capacity + 1) < std::max(new_usg, new_plan) * 32 / (new_cap + 1)) {
|
||||
cargo.capacity = new_cap;
|
||||
cargo.usage = new_usg;
|
||||
cargo.planned = new_plan;
|
||||
@@ -272,7 +272,7 @@ void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
|
||||
*/
|
||||
void LinkGraphOverlay::DrawContent(Point pta, Point ptb, const LinkProperties &cargo) const
|
||||
{
|
||||
uint usage_or_plan = min(cargo.capacity * 2 + 1, max(cargo.usage, cargo.planned));
|
||||
uint usage_or_plan = std::min(cargo.capacity * 2 + 1, std::max(cargo.usage, cargo.planned));
|
||||
int colour = LinkGraphOverlay::LINK_COLOURS[usage_or_plan * lengthof(LinkGraphOverlay::LINK_COLOURS) / (cargo.capacity * 2 + 2)];
|
||||
int dash = cargo.shared ? this->scale * 4 : 0;
|
||||
|
||||
@@ -302,7 +302,7 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
|
||||
Point pt = this->GetStationMiddle(st);
|
||||
if (!this->IsPointVisible(pt, dpi, 3 * this->scale)) continue;
|
||||
|
||||
uint r = this->scale * 2 + this->scale * 2 * min(200, i->second) / 200;
|
||||
uint r = this->scale * 2 + this->scale * 2 * std::min(200U, i->second) / 200;
|
||||
|
||||
LinkGraphOverlay::DrawVertex(pt.x, pt.y, r,
|
||||
_colour_gradient[st->owner != OWNER_NONE ?
|
||||
@@ -455,7 +455,7 @@ static const NWidgetPart _nested_linkgraph_legend_widgets[] = {
|
||||
EndContainer()
|
||||
};
|
||||
|
||||
assert_compile(WID_LGL_SATURATION_LAST - WID_LGL_SATURATION_FIRST ==
|
||||
static_assert(WID_LGL_SATURATION_LAST - WID_LGL_SATURATION_FIRST ==
|
||||
lengthof(LinkGraphOverlay::LINK_COLOURS) - 1);
|
||||
|
||||
static WindowDesc _linkgraph_legend_desc(
|
||||
|
||||
@@ -37,7 +37,9 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig) :
|
||||
* This is on purpose. */
|
||||
link_graph(orig),
|
||||
settings(_settings_game.linkgraph),
|
||||
join_date(_date + _settings_game.linkgraph.recalc_time)
|
||||
join_date(_date + _settings_game.linkgraph.recalc_time),
|
||||
job_completed(false),
|
||||
job_aborted(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -91,6 +93,11 @@ LinkGraphJob::~LinkGraphJob()
|
||||
* Accessing other pools may be invalid. */
|
||||
if (CleaningPool()) return;
|
||||
|
||||
/* If the job has been aborted, the job state is invalid.
|
||||
* This should never be reached, as once the job has been marked as aborted
|
||||
* the only valid job operation is to clear the LinkGraphJob pool. */
|
||||
assert(!this->IsJobAborted());
|
||||
|
||||
/* Link graph has been merged into another one. */
|
||||
if (!LinkGraph::IsValidID(this->link_graph.index)) return;
|
||||
|
||||
@@ -216,8 +223,8 @@ void LinkGraphJob::NodeAnnotation::Init(uint supply)
|
||||
*/
|
||||
void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
|
||||
{
|
||||
this->capacity = min(base->capacity, cap);
|
||||
this->free_capacity = min(base->free_capacity, free_cap);
|
||||
this->capacity = std::min(base->capacity, cap);
|
||||
this->free_capacity = std::min(base->free_capacity, free_cap);
|
||||
this->distance = base->distance + dist;
|
||||
assert(this->distance > 0);
|
||||
if (this->parent != base) {
|
||||
@@ -243,7 +250,7 @@ uint Path::AddFlow(uint new_flow, LinkGraphJob &job, uint max_saturation)
|
||||
if (max_saturation != UINT_MAX) {
|
||||
uint usable_cap = edge.Capacity() * max_saturation / 100;
|
||||
if (usable_cap > edge.Flow()) {
|
||||
new_flow = min(new_flow, usable_cap - edge.Flow());
|
||||
new_flow = std::min(new_flow, usable_cap - edge.Flow());
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../thread.h"
|
||||
#include "linkgraph.h"
|
||||
#include <list>
|
||||
#include <atomic>
|
||||
|
||||
class LinkGraphJob;
|
||||
class Path;
|
||||
@@ -61,6 +62,8 @@ protected:
|
||||
Date join_date; ///< Date when the job is to be joined.
|
||||
NodeAnnotationVector nodes; ///< Extra node data necessary for link graph calculation.
|
||||
EdgeAnnotationMatrix edges; ///< Extra edge data necessary for link graph calculation.
|
||||
std::atomic<bool> job_completed; ///< Is the job still running. This is accessed by multiple threads and reads may be stale.
|
||||
std::atomic<bool> job_aborted; ///< Has the job been aborted. This is accessed by multiple threads and reads may be stale.
|
||||
|
||||
void EraseFlows(NodeID from);
|
||||
void JoinThread();
|
||||
@@ -160,9 +163,9 @@ public:
|
||||
* @return Pair of the edge currently pointed to and the ID of its
|
||||
* other end.
|
||||
*/
|
||||
SmallPair<NodeID, Edge> operator*() const
|
||||
std::pair<NodeID, Edge> operator*() const
|
||||
{
|
||||
return SmallPair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
|
||||
return std::pair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,18 +268,40 @@ public:
|
||||
* settings have to be brutally const-casted in order to populate them.
|
||||
*/
|
||||
LinkGraphJob() : settings(_settings_game.linkgraph),
|
||||
join_date(INVALID_DATE) {}
|
||||
join_date(INVALID_DATE), job_completed(false), job_aborted(false) {}
|
||||
|
||||
LinkGraphJob(const LinkGraph &orig);
|
||||
~LinkGraphJob();
|
||||
|
||||
void Init();
|
||||
|
||||
/**
|
||||
* Check if job has actually finished.
|
||||
* This is allowed to spuriously return an incorrect value.
|
||||
* @return True if job has actually finished.
|
||||
*/
|
||||
inline bool IsJobCompleted() const { return this->job_completed.load(std::memory_order_acquire); }
|
||||
|
||||
/**
|
||||
* Check if job has been aborted.
|
||||
* This is allowed to spuriously return false incorrectly, but is not allowed to incorrectly return true.
|
||||
* @return True if job has been aborted.
|
||||
*/
|
||||
inline bool IsJobAborted() const { return this->job_aborted.load(std::memory_order_acquire); }
|
||||
|
||||
/**
|
||||
* Abort job.
|
||||
* The job may exit early at the next available opportunity.
|
||||
* After this method has been called the state of the job is undefined, and the only valid operation
|
||||
* is to join the thread and discard the job data.
|
||||
*/
|
||||
inline void AbortJob() { this->job_aborted.store(true, std::memory_order_release); }
|
||||
|
||||
/**
|
||||
* Check if job is supposed to be finished.
|
||||
* @return True if job should be finished by now, false if not.
|
||||
*/
|
||||
inline bool IsFinished() const { return this->join_date <= _date; }
|
||||
inline bool IsScheduledToBeJoined() const { return this->join_date <= _date; }
|
||||
|
||||
/**
|
||||
* Get the date when the job should be finished.
|
||||
@@ -367,7 +392,7 @@ public:
|
||||
*/
|
||||
inline static int GetCapacityRatio(int free, uint total)
|
||||
{
|
||||
return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / max(total, 1U);
|
||||
return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / std::max(total, 1U);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "mcf.h"
|
||||
#include "flowmapper.h"
|
||||
#include "../framerate_type.h"
|
||||
#include "../command_func.h"
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
@@ -48,6 +50,17 @@ void LinkGraphSchedule::SpawnNext()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the next job is supposed to be finished, but has not yet completed.
|
||||
* @return True if job should be finished by now but is still running, false if not.
|
||||
*/
|
||||
bool LinkGraphSchedule::IsJoinWithUnfinishedJobDue() const
|
||||
{
|
||||
if (this->running.empty()) return false;
|
||||
const LinkGraphJob *next = this->running.front();
|
||||
return next->IsScheduledToBeJoined() && !next->IsJobCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the next finished job, if available.
|
||||
*/
|
||||
@@ -55,7 +68,7 @@ void LinkGraphSchedule::JoinNext()
|
||||
{
|
||||
if (this->running.empty()) return;
|
||||
LinkGraphJob *next = this->running.front();
|
||||
if (!next->IsFinished()) return;
|
||||
if (!next->IsScheduledToBeJoined()) return;
|
||||
this->running.pop_front();
|
||||
LinkGraphID id = next->LinkGraphIndex();
|
||||
delete next; // implicitly joins the thread
|
||||
@@ -73,8 +86,21 @@ void LinkGraphSchedule::JoinNext()
|
||||
/* static */ void LinkGraphSchedule::Run(LinkGraphJob *job)
|
||||
{
|
||||
for (uint i = 0; i < lengthof(instance.handlers); ++i) {
|
||||
if (job->IsJobAborted()) return;
|
||||
instance.handlers[i]->Run(*job);
|
||||
}
|
||||
|
||||
/*
|
||||
* Readers of this variable in another thread may see an out of date value.
|
||||
* However this is OK as this will only happen just as a job is completing,
|
||||
* and the real synchronisation is provided by the thread join operation.
|
||||
* In the worst case the main thread will be paused for longer than
|
||||
* strictly necessary before joining.
|
||||
* This is just a hint variable to avoid performing the join excessively
|
||||
* early and blocking the main thread.
|
||||
*/
|
||||
|
||||
job->job_completed.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +120,7 @@ void LinkGraphSchedule::SpawnAll()
|
||||
/* static */ void LinkGraphSchedule::Clear()
|
||||
{
|
||||
for (JobList::iterator i(instance.running.begin()); i != instance.running.end(); ++i) {
|
||||
(*i)->JoinThread();
|
||||
(*i)->AbortJob();
|
||||
}
|
||||
instance.running.clear();
|
||||
instance.schedule.clear();
|
||||
@@ -135,6 +161,42 @@ LinkGraphSchedule::~LinkGraphSchedule()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause the game if in 2 _date_fract ticks, we would do a join with the next
|
||||
* link graph job, but it is still running.
|
||||
* The check is done 2 _date_fract ticks early instead of 1, as in multiplayer
|
||||
* calls to DoCommandP are executed after a delay of 1 _date_fract tick.
|
||||
* If we previously paused, unpause if the job is now ready to be joined with.
|
||||
*/
|
||||
void StateGameLoop_LinkGraphPauseControl()
|
||||
{
|
||||
if (_pause_mode & PM_PAUSED_LINK_GRAPH) {
|
||||
/* We are paused waiting on a job, check the job every tick. */
|
||||
if (!LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) {
|
||||
DoCommandP(0, PM_PAUSED_LINK_GRAPH, 0, CMD_PAUSE);
|
||||
}
|
||||
} else if (_pause_mode == PM_UNPAUSED &&
|
||||
_date_fract == LinkGraphSchedule::SPAWN_JOIN_TICK - 2 &&
|
||||
_date % _settings_game.linkgraph.recalc_interval == _settings_game.linkgraph.recalc_interval / 2 &&
|
||||
LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) {
|
||||
/* Perform check two _date_fract ticks before we would join, to make
|
||||
* sure it also works in multiplayer. */
|
||||
DoCommandP(0, PM_PAUSED_LINK_GRAPH, 1, CMD_PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause the game on load if we would do a join with the next link graph job,
|
||||
* but it is still running, and it would not be caught by a call to
|
||||
* StateGameLoop_LinkGraphPauseControl().
|
||||
*/
|
||||
void AfterLoad_LinkGraphPauseControl()
|
||||
{
|
||||
if (LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) {
|
||||
_pause_mode |= PM_PAUSED_LINK_GRAPH;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn or join a link graph job or compress a link graph if any link graph is
|
||||
* due to do so.
|
||||
@@ -146,8 +208,13 @@ void OnTick_LinkGraph()
|
||||
if (offset == 0) {
|
||||
LinkGraphSchedule::instance.SpawnNext();
|
||||
} else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
|
||||
PerformanceMeasurer framerate(PFE_GL_LINKGRAPH);
|
||||
LinkGraphSchedule::instance.JoinNext();
|
||||
if (!_networking || _network_server) {
|
||||
PerformanceMeasurer::SetInactive(PFE_GL_LINKGRAPH);
|
||||
LinkGraphSchedule::instance.JoinNext();
|
||||
} else {
|
||||
PerformanceMeasurer framerate(PFE_GL_LINKGRAPH);
|
||||
LinkGraphSchedule::instance.JoinNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
static void Clear();
|
||||
|
||||
void SpawnNext();
|
||||
bool IsJoinWithUnfinishedJobDue() const;
|
||||
void JoinNext();
|
||||
void SpawnAll();
|
||||
void ShiftDates(int interval);
|
||||
@@ -76,4 +77,7 @@ public:
|
||||
void Unqueue(LinkGraph *lg) { this->schedule.remove(lg); }
|
||||
};
|
||||
|
||||
void StateGameLoop_LinkGraphPauseControl();
|
||||
void AfterLoad_LinkGraphPauseControl();
|
||||
|
||||
#endif /* LINKGRAPHSCHEDULE_H */
|
||||
|
||||
@@ -235,7 +235,7 @@ bool DistanceAnnotation::IsBetter(const DistanceAnnotation *base, uint cap,
|
||||
bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
|
||||
int free_cap, uint dist) const
|
||||
{
|
||||
int min_cap = Path::GetCapacityRatio(min(base->free_capacity, free_cap), min(base->capacity, cap));
|
||||
int min_cap = Path::GetCapacityRatio(std::min(base->free_capacity, free_cap), std::min(base->capacity, cap));
|
||||
int this_cap = this->GetCapacityRatio();
|
||||
if (min_cap == this_cap) {
|
||||
/* If the capacities are the same and the other path isn't disconnected
|
||||
@@ -354,7 +354,7 @@ uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
|
||||
uint flow = UINT_MAX;
|
||||
const Path *cycle_end = cycle_begin;
|
||||
do {
|
||||
flow = min(flow, cycle_begin->GetFlow());
|
||||
flow = std::min(flow, cycle_begin->GetFlow());
|
||||
cycle_begin = path[cycle_begin->GetNode()];
|
||||
} while (cycle_begin != cycle_end);
|
||||
return flow;
|
||||
@@ -528,7 +528,7 @@ MCF1stPass::MCF1stPass(LinkGraphJob &job) : MultiCommodityFlow(job)
|
||||
finished_sources[source] = !source_demand_left;
|
||||
this->CleanupPaths(source, paths);
|
||||
}
|
||||
} while (more_loops || this->EliminateCycles());
|
||||
} while ((more_loops || this->EliminateCycles()) && !job.IsJobAborted());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,7 +544,7 @@ MCF2ndPass::MCF2ndPass(LinkGraphJob &job) : MultiCommodityFlow(job)
|
||||
uint accuracy = job.Settings().accuracy;
|
||||
bool demand_left = true;
|
||||
std::vector<bool> finished_sources(size);
|
||||
while (demand_left) {
|
||||
while (demand_left && !job.IsJobAborted()) {
|
||||
demand_left = false;
|
||||
for (NodeID source = 0; source < size; ++source) {
|
||||
if (finished_sources[source]) continue;
|
||||
|
||||
Reference in New Issue
Block a user