Files @ r24835:3784c0862167
Branch filter:

Location: cpp/openttd-patchpack/source/src/linkgraph/mcf.h - annotation

Patric Stout
Change: sleep till the next tick in the main loop

Sleep for 1ms (which is always (a lot) more than 1ms) is just
randomly guessing and hoping you hit your deadline, give or take.

But given we can calculate when our next frame is happening, we
can just sleep for that exact amount. As these values are often
a bit larger, it is also more likely the OS can schedule us back
in close to our requested target. This means it is more likely we
hit our deadlines, which makes the FPS a lot more stable.
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
r20343:f2d4e3211203
/** @file mcf.h Declaration of Multi-Commodity-Flow solver */

#ifndef MCF_H
#define MCF_H

#include "linkgraphjob_base.h"
#include <vector>

typedef std::vector<Path *> PathVector;

/**
 * Multi-commodity flow calculating base class.
 */
class MultiCommodityFlow {
protected:
	/**
	 * Constructor.
	 * @param job Link graph job being executed.
	 */
	MultiCommodityFlow(LinkGraphJob &job) : job(job),
			max_saturation(job.Settings().short_path_saturation)
	{}

	template<class Tannotation, class Tedge_iterator>
	void Dijkstra(NodeID from, PathVector &paths);

	uint PushFlow(Edge &edge, Path *path, uint accuracy, uint max_saturation);

	void CleanupPaths(NodeID source, PathVector &paths);

	LinkGraphJob &job;   ///< Job we're working with.
	uint max_saturation; ///< Maximum saturation for edges.
};

/**
 * First pass of the MCF calculation. Saturates shortest paths first, creates
 * new paths if needed, eliminates cycles. This calculation is of exponential
 * complexity in the number of nodes but the constant factors are sufficiently
 * small to make it usable for most real-life link graph components. You can
 * deal with performance problems that might occur here in multiple ways:
 * - The overall accuracy is used here to determine how much flow is assigned
 *   in each loop. The lower the accuracy, the more flow is assigned, the less
 *   loops it takes to assign all flow.
 * - The short_path_saturation setting determines when this pass stops. The
 *   lower you set it, the less flow will be assigned in this pass, the less
 *   time it will take.
 * - You can increase the recalculation interval to allow for longer running
 *   times without creating lags.
 */
class MCF1stPass : public MultiCommodityFlow {
private:
	bool EliminateCycles();
	bool EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id);
	void EliminateCycle(PathVector &path, Path *cycle_begin, uint flow);
	uint FindCycleFlow(const PathVector &path, const Path *cycle_begin);
public:
	MCF1stPass(LinkGraphJob &job);
};

/**
 * Second pass of the MCF calculation. Saturates paths with most capacity left
 * first and doesn't create any paths along edges that haven't been visited in
 * the first pass. This is why it doesn't have to do any cycle detection and
 * elimination. As cycle detection is the most intense problem in the first
 * pass this pass is cheaper. The accuracy is used here, too.
 */
class MCF2ndPass : public MultiCommodityFlow {
public:
	MCF2ndPass(LinkGraphJob &job);
};

/**
 * Link graph handler for MCF. Creates MultiCommodityFlow instance according to
 * the template parameter.
 */
template<class Tpass>
class MCFHandler : public ComponentHandler {
public:

	/**
	 * Run the calculation.
	 * @param graph Component to be calculated.
	 */
	virtual void Run(LinkGraphJob &job) const { Tpass pass(job); }

	/**
	 * Destructor. Has to be given because of virtual Run().
	 */
	virtual ~MCFHandler() {}
};

#endif /* MCF_H */