Changeset - r20854:d6b61e2cf909
[Not reviewed]
master
0 5 0
fonsinchen - 11 years ago 2013-10-22 16:13:28
fonsinchen@openttd.org
(svn r25898) -Codechange: Add second timestamp for 'restricted links' to all edges.
5 files changed with 104 insertions and 31 deletions:
0 comments (0 inline, 0 general)
src/linkgraph/linkgraph.cpp
Show inline comments
 
@@ -36,13 +36,14 @@ inline void LinkGraph::BaseNode::Init(St
 
 */
 
inline void LinkGraph::BaseEdge::Init(uint distance)
 
{
 
	this->distance = distance;
 
	this->capacity = 0;
 
	this->usage = 0;
 
	this->last_update = INVALID_DATE;
 
	this->last_unrestricted_update = INVALID_DATE;
 
	this->last_restricted_update = INVALID_DATE;
 
	this->next_edge = INVALID_NODE;
 
}
 

	
 
/**
 
 * Shift all dates by given interval.
 
 * This is useful if the date has been modified with the cheat menu.
 
@@ -53,13 +54,14 @@ void LinkGraph::ShiftDates(int interval)
 
	this->last_compression += interval;
 
	for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
 
		BaseNode &source = this->nodes[node1];
 
		if (source.last_update != INVALID_DATE) source.last_update += interval;
 
		for (NodeID node2 = 0; node2 < this->Size(); ++node2) {
 
			BaseEdge &edge = this->edges[node1][node2];
 
			if (edge.last_update != INVALID_DATE) edge.last_update += interval;
 
			if (edge.last_unrestricted_update != INVALID_DATE) edge.last_unrestricted_update += interval;
 
			if (edge.last_restricted_update != INVALID_DATE) edge.last_restricted_update += interval;
 
		}
 
	}
 
}
 

	
 
void LinkGraph::Compress()
 
{
 
@@ -175,33 +177,50 @@ NodeID LinkGraph::AddNode(const Station 
 
		this->edges[i][new_node].Init(distance);
 
	}
 
	return new_node;
 
}
 

	
 
/**
 
 * Fill an edge with values from a link.
 
 * Fill an edge with values from a link. If usage < capacity set the usage,
 
 * otherwise set the restricted or unrestricted update timestamp.
 
 * @param to Destination node of the link.
 
 * @param capacity Capacity of the link.
 
 * @param usage Usage to be added or REFRESH_UNRESTRICTED or REFRESH_RESTRICTED.
 
 */
 
void LinkGraph::Node::AddEdge(NodeID to, uint capacity, uint usage)
 
{
 
	assert(this->index != to);
 
	BaseEdge &edge = this->edges[to];
 
	BaseEdge &first = this->edges[this->index];
 
	edge.capacity = capacity;
 
	edge.usage = usage == UINT_MAX ? 0 : usage;
 
	edge.next_edge = first.next_edge;
 
	first.next_edge = to;
 
	edge.last_update = _date;
 
	switch (usage) {
 
		case REFRESH_UNRESTRICTED:
 
			edge.last_unrestricted_update = _date;
 
			break;
 
		case REFRESH_RESTRICTED:
 
			edge.last_restricted_update = _date;
 
			break;
 
		default:
 
			edge.usage = usage;
 
			break;
 
	}
 
}
 

	
 
/**
 
 * Creates an edge if none exists yet or updates an existing edge.
 
 * @param to Target node.
 
 * @param capacity Capacity of the link.
 
 * @param usage Usage to be added or REFRESH_UNRESTRICTED or REFRESH_RESTRICTED.
 
 */
 
void LinkGraph::Node::UpdateEdge(NodeID to, uint capacity, uint usage)
 
{
 
	assert(capacity > 0);
 
	assert(usage <= capacity || usage == UINT_MAX);
 
	if (this->edges[to].last_update == INVALID_DATE) {
 
	assert(usage <= capacity || usage == REFRESH_RESTRICTED || usage == REFRESH_UNRESTRICTED);
 
	if (this->edges[to].capacity == 0) {
 
		this->AddEdge(to, capacity, usage);
 
	} else {
 
		(*this)[to].Update(capacity, usage);
 
	}
 
}
 

	
 
@@ -211,13 +230,14 @@ void LinkGraph::Node::UpdateEdge(NodeID 
 
 */
 
void LinkGraph::Node::RemoveEdge(NodeID to)
 
{
 
	if (this->index == to) return;
 
	BaseEdge &edge = this->edges[to];
 
	edge.capacity = 0;
 
	edge.last_update = INVALID_DATE;
 
	edge.last_unrestricted_update = INVALID_DATE;
 
	edge.last_restricted_update = INVALID_DATE;
 
	edge.usage = 0;
 

	
 
	NodeID prev = this->index;
 
	NodeID next = this->edges[this->index].next_edge;
 
	while (next != INVALID_NODE) {
 
		if (next == to) {
 
@@ -230,30 +250,40 @@ void LinkGraph::Node::RemoveEdge(NodeID 
 
			next = this->edges[next].next_edge;
 
		}
 
	}
 
}
 

	
 
/**
 
 * Create a new edge or update an existing one. If usage is UINT_MAX refresh
 
 * the edge to have at least the given capacity, otherwise add the capacity.
 
 * Create a new edge or update an existing one. If usage is REFRESH_UNRESTRICTED
 
 * or REFRESH_RESTRICTED refresh the edge to have at least the given capacity
 
 * and also update the respective update timestamp, otherwise add the capacity.
 
 * @param from Start node of the edge.
 
 * @param to End node of the edge.
 
 * @param capacity Capacity to be added/updated.
 
 * @param usage Usage to be added or UINT_MAX.
 
 * @param usage Usage to be added or REFRESH_UNRESTRICTED or REFRESH_RESTRICTED.
 
 */
 
void LinkGraph::Edge::Update(uint capacity, uint usage)
 
{
 
	assert(this->edge.capacity > 0);
 
	if (usage == UINT_MAX) {
 
	if (usage > capacity) {
 
		this->edge.capacity = max(this->edge.capacity, capacity);
 
		switch (usage) {
 
			case REFRESH_UNRESTRICTED:
 
				this->edge.last_unrestricted_update = _date;
 
				break;
 
			case REFRESH_RESTRICTED:
 
				this->edge.last_restricted_update = _date;
 
				break;
 
			default:
 
				NOT_REACHED();
 
				break;
 
		}
 
	} else {
 
		assert(capacity >= usage);
 
		this->edge.capacity += capacity;
 
		this->edge.usage += usage;
 
	}
 
	this->edge.last_update = _date;
 
}
 

	
 
/**
 
 * Resize the component and fill it with empty nodes and edges. Used when
 
 * loading from save games. The component is expected to be empty before.
 
 * @param size New size of the component.
src/linkgraph/linkgraph.h
Show inline comments
 
@@ -38,12 +38,28 @@ extern LinkGraphPool _link_graph_pool;
 
 * might change between the creation and join time so we can't rely on them.
 
 */
 
class LinkGraph : public LinkGraphPool::PoolItem<&_link_graph_pool> {
 
public:
 

	
 
	/**
 
	 * Special modes for updating links. 'Restricted' means that vehicles with
 
	 * 'no loading' orders are serving the link. If a link is only served by
 
	 * such vehicles it's 'fully restricted'. This means the link can be used
 
	 * by cargo arriving in such vehicles, but not by cargo generated or
 
	 * transferring at the source station of the link. In order to find out
 
	 * about this condition we keep two update timestamps in each link, one for
 
	 * the restricted and one for the unrestricted part of it. If either one
 
	 * times out while the other is still valid the link becomes fully
 
	 * restricted or fully unrestricted, respectively.
 
	 */
 
	enum UpdateMode {
 
		REFRESH_RESTRICTED = UINT_MAX - 1, ///< Refresh restricted link.
 
		REFRESH_UNRESTRICTED = UINT_MAX    ///< Refresh unrestricted link.
 
	};
 

	
 
	/**
 
	 * Node of the link graph. contains all relevant information from the associated
 
	 * station. It's copied so that the link graph job can work on its own data set
 
	 * in a separate thread.
 
	 */
 
	struct BaseNode {
 
		uint supply;             ///< Supply at the station.
 
@@ -57,17 +73,18 @@ public:
 
	 * An edge in the link graph. Corresponds to a link between two stations or at
 
	 * least the distance between them. Edges from one node to itself contain the
 
	 * ID of the opposite Node of the first active edge (i.e. not just distance) in
 
	 * the column as next_edge.
 
	 */
 
	struct BaseEdge {
 
		uint distance;    ///< Length of the link.
 
		uint capacity;    ///< Capacity of the link.
 
		uint usage;       ///< Usage of the link.
 
		Date last_update; ///< When the link was last updated.
 
		NodeID next_edge; ///< Destination of next valid edge starting at the same source node.
 
		uint distance;                 ///< Length of the link.
 
		uint capacity;                 ///< Capacity of the link.
 
		uint usage;                    ///< Usage of the link.
 
		Date last_unrestricted_update; ///< When the unrestricted part of the link was last updated.
 
		Date last_restricted_update;   ///< When the restricted part of the link was last updated.
 
		NodeID next_edge;              ///< Destination of next valid edge starting at the same source node.
 
		void Init(uint distance = 0);
 
	};
 

	
 
	/**
 
	 * Wrapper for an edge (const or not) allowing retrieval, but no modification.
 
	 * @tparam Tedge Actual edge class, may be "const BaseEdge" or just "BaseEdge".
 
@@ -101,16 +118,28 @@ public:
 
		 * Get edge's distance.
 
		 * @return Distance.
 
		 */
 
		uint Distance() const { return this->edge.distance; }
 

	
 
		/**
 
		 * Get edge's last update.
 
		 * Get the date of the last update to the edge's unrestricted capacity.
 
		 * @return Last update.
 
		 */
 
		Date LastUpdate() const { return this->edge.last_update; }
 
		Date LastUnrestrictedUpdate() const { return this->edge.last_unrestricted_update; }
 

	
 
		/**
 
		 * Get the date of the last update to the edge's restricted capacity.
 
		 * @return Last update.
 
		 */
 
		Date LastRestrictedUpdate() const { return this->edge.last_restricted_update; }
 

	
 
		/**
 
		 * 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); }
 
	};
 

	
 
	/**
 
	 * Wrapper for a node (const or not) allowing retrieval, but no modification.
 
	 * @tparam Tedge Actual node class, may be "const BaseNode" or just "BaseNode".
 
	 * @tparam Tedge Actual edge class, may be "const BaseEdge" or just "BaseEdge".
 
@@ -282,12 +311,14 @@ public:
 
		/**
 
		 * Constructor
 
		 * @param edge Edge to be wrapped.
 
		 */
 
		Edge(BaseEdge &edge) : EdgeWrapper<BaseEdge>(edge) {}
 
		void Update(uint capacity, uint usage);
 
		void Restrict() { this->edge.last_unrestricted_update = INVALID_DATE; }
 
		void Release() { this->edge.last_restricted_update = INVALID_DATE; }
 
	};
 

	
 
	/**
 
	 * An iterator for const edges. Cannot be typedef'ed because of
 
	 * template-reference to ConstEdgeIterator itself.
 
	 */
src/saveload/linkgraph_sl.cpp
Show inline comments
 
@@ -115,18 +115,19 @@ static const SaveLoad _node_desc[] = {
 
};
 

	
 
/**
 
 * SaveLoad desc for a link graph edge.
 
 */
 
static const SaveLoad _edge_desc[] = {
 
	SLE_VAR(Edge, distance,    SLE_UINT32),
 
	SLE_VAR(Edge, capacity,    SLE_UINT32),
 
	SLE_VAR(Edge, usage,       SLE_UINT32),
 
	SLE_VAR(Edge, last_update, SLE_INT32),
 
	SLE_VAR(Edge, next_edge,   SLE_UINT16),
 
	SLE_END()
 
	    SLE_VAR(Edge, distance,                 SLE_UINT32),
 
	    SLE_VAR(Edge, capacity,                 SLE_UINT32),
 
	    SLE_VAR(Edge, usage,                    SLE_UINT32),
 
	    SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
 
	SLE_CONDVAR(Edge, last_restricted_update,   SLE_INT32, 187, SL_MAX_VERSION),
 
	    SLE_VAR(Edge, next_edge,                SLE_UINT16),
 
	    SLE_END()
 
};
 

	
 
/**
 
 * Save/load a link graph.
 
 * @param comp Link graph to be saved or loaded.
 
 */
src/station_cmd.cpp
Show inline comments
 
@@ -3414,19 +3414,24 @@ void DeleteStaleLinks(Station *from)
 
		if (lg == NULL) continue;
 
		Node node = (*lg)[ge.node];
 
		for (EdgeIterator it(node.Begin()); it != node.End();) {
 
			Edge edge = it->second;
 
			Station *to = Station::Get((*lg)[it->first].Station());
 
			assert(to->goods[c].node == it->first);
 
			++it; // Do that before removing the node. Anything else may crash.
 
			++it; // Do that before removing the edge. Anything else may crash.
 
			assert(_date >= edge.LastUpdate());
 
			if ((uint)(_date - edge.LastUpdate()) > LinkGraph::MIN_TIMEOUT_DISTANCE +
 
					(DistanceManhattan(from->xy, to->xy) >> 2)) {
 
			uint timeout = LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 2);
 
			if ((uint)(_date - edge.LastUpdate()) > timeout) {
 
				node.RemoveEdge(to->goods[c].node);
 
				ge.flows.DeleteFlows(to->index);
 
				RerouteCargo(from, c, to->index, from->index);
 
			} else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastUnrestrictedUpdate()) > timeout) {
 
				edge.Restrict();
 
				RerouteCargo(from, c, to->index, from->index);
 
			} else if (edge.LastRestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastRestrictedUpdate()) > timeout) {
 
				edge.Release();
 
			}
 
		}
 
		assert(_date >= lg->LastCompression());
 
		if ((uint)(_date - lg->LastCompression()) > LinkGraph::COMPRESSION_INTERVAL) {
 
			lg->Compress();
 
		}
src/vehicle.cpp
Show inline comments
 
@@ -47,12 +47,13 @@
 
#include "effectvehicle_base.h"
 
#include "vehiclelist.h"
 
#include "bridge_map.h"
 
#include "tunnel_map.h"
 
#include "depot_map.h"
 
#include "gamelog.h"
 
#include "linkgraph/linkgraph.h"
 

	
 
#include "table/strings.h"
 

	
 
#define GEN_HASH(x, y) ((GB((y), 6 + ZOOM_LVL_SHIFT, 6) << 6) + GB((x), 7 + ZOOM_LVL_SHIFT, 6))
 

	
 
VehicleID _new_vehicle_id;
 
@@ -2264,13 +2265,18 @@ uint Vehicle::RefreshNextHopsStats(Capac
 
				if (has_cargo) {
 
					StationID next_station = next->GetDestination();
 
					Station *st = Station::GetIfValid(cur->GetDestination());
 
					if (st != NULL && next_station != INVALID_STATION && next_station != st->index) {
 
						for (CapacitiesMap::const_iterator i = capacities.begin(); i != capacities.end(); ++i) {
 
							/* Refresh the link and give it a minimum capacity. */
 
							if (i->second > 0) IncreaseStats(st, i->first, next_station, i->second, UINT_MAX);
 
							if (i->second > 0) {
 
								/* A link is at least partly restricted if a
 
								 * vehicle can't load at its source. */
 
								IncreaseStats(st, i->first, next_station, i->second,
 
										(cur->GetLoadType() & OLFB_NO_LOAD) == 0 ? LinkGraph::REFRESH_UNRESTRICTED : LinkGraph::REFRESH_RESTRICTED);
 
							}
 
						}
 
					}
 
				}
 
			}
 

	
 
			/* "cur" is only assigned here if the stop is a station so that
0 comments (0 inline, 0 general)