Changeset - r13219:41299110cd66
[Not reviewed]
master
0 2 0
rubidium - 15 years ago 2009-10-07 08:31:42
rubidium@openttd.org
(svn r17736) -Codechange [FS#3135]: rewrite CargoList::MoveTo; don't require the secondary list, use cache updates instead of rebuilds. This is usually faster because of primarily gradual loading that only moves a (small) part of the cargo each time. Based on patch by fonsinchen.
2 files changed with 51 insertions and 51 deletions:
0 comments (0 inline, 0 general)
src/cargopacket.cpp
Show inline comments
 
@@ -140,102 +140,102 @@ void CargoList::Truncate(uint max_remain
 
			uint diff = local_count - max_remaining;
 
			this->count -= diff;
 
			this->cargo_days_in_transit -= cp->days_in_transit * diff;
 
			cp->count = max_remaining;
 
			max_remaining = 0;
 
		} else {
 
			max_remaining -= local_count;
 
		}
 
		++it;
 
	}
 
}
 

	
 
bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, CargoPayment *payment, uint data)
 
bool CargoList::MoveTo(CargoList *dest, uint max_move, CargoList::MoveToAction mta, CargoPayment *payment, uint data)
 
{
 
	assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
 
	assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
 
	CargoList tmp;
 

	
 
	while (!this->packets.empty() && count > 0) {
 
		CargoPacket *cp = *packets.begin();
 
		if (cp->count <= count) {
 
	List::iterator it = packets.begin();
 
	while (it != packets.end() && max_move > 0) {
 
		CargoPacket *cp = *it;
 
		if (cp->source == data && mta == MTA_FINAL_DELIVERY) {
 
			/* Skip cargo that originated from this station. */
 
			++it;
 
			continue;
 
		}
 

	
 
		if (cp->count <= max_move) {
 
			/* Can move the complete packet */
 
			this->packets.remove(cp);
 
			switch (mta) {
 
			max_move -= cp->count;
 
			this->packets.erase(it++);
 
			this->RemoveFromCache(cp);
 
			switch(mta) {
 
				case MTA_FINAL_DELIVERY:
 
					if (cp->source == data) {
 
						tmp.Append(cp);
 
					} else {
 
						payment->PayFinalDelivery(cp, cp->count);
 
						count -= cp->count;
 
						delete cp;
 
					}
 
					payment->PayFinalDelivery(cp, cp->count);
 
					delete cp;
 
					continue; // of the loop
 

	
 
				case MTA_CARGO_LOAD:
 
					cp->loaded_at_xy = data;
 
					break;
 

	
 
				case MTA_TRANSFER:
 
					cp->feeder_share += payment->PayTransfer(cp, cp->count);
 
					break;
 

	
 
				case MTA_UNLOAD:
 
					break;
 
			}
 
			count -= cp->count;
 
			dest->packets.push_back(cp);
 
		} else {
 
			/* Can move only part of the packet, so split it into two pieces */
 
			if (mta != MTA_FINAL_DELIVERY) {
 
				CargoPacket *cp_new = new CargoPacket();
 
			dest->Append(cp);
 
			continue;
 
		}
 

	
 
				Money fs = cp->feeder_share * count / static_cast<uint>(cp->count);
 
				cp->feeder_share -= fs;
 

	
 
				cp_new->source          = cp->source;
 
				cp_new->source_xy       = cp->source_xy;
 
				cp_new->loaded_at_xy    = (mta == MTA_CARGO_LOAD) ? data : cp->loaded_at_xy;
 
		/* Can move only part of the packet */
 
		if (mta == MTA_FINAL_DELIVERY) {
 
			/* Final delivery doesn't need package splitting. */
 
			payment->PayFinalDelivery(cp, max_move);
 
			this->count -= max_move;
 
			this->cargo_days_in_transit -= max_move * cp->days_in_transit;
 

	
 
				cp_new->days_in_transit = cp->days_in_transit;
 
				cp_new->feeder_share    = fs;
 
			/* Final delivery payment pays the feeder share, so we have to
 
			 * reset that so it is not 'shown' twice for partial unloads. */
 
			this->feeder_share -= cp->feeder_share;
 
			cp->feeder_share = 0;
 
		} else {
 
			/* But... the rest needs package splitting. */
 
			Money fs = cp->feeder_share * max_move / static_cast<uint>(cp->count);
 
			cp->feeder_share -= fs;
 

	
 
				cp_new->source_type     = cp->source_type;
 
				cp_new->source_id       = cp->source_id;
 

	
 
				cp_new->count = count;
 
				dest->packets.push_back(cp_new);
 
			CargoPacket *cp_new = new CargoPacket(max_move, cp->days_in_transit, fs, cp->source_type, cp->source_id);
 

	
 
				if (mta == MTA_TRANSFER) cp_new->feeder_share += payment->PayTransfer(cp_new, count);
 
			} else {
 
				payment->PayFinalDelivery(cp, count);
 
			cp_new->source          = cp->source;
 
			cp_new->source_xy       = cp->source_xy;
 
			cp_new->loaded_at_xy    = (mta == MTA_CARGO_LOAD) ? data : cp->loaded_at_xy;
 

	
 
			this->RemoveFromCache(cp_new); // this reflects the changes in cp.
 

	
 
			if (mta == MTA_TRANSFER) {
 
				/* Add the feeder share before inserting in dest. */
 
				cp_new->feeder_share += payment->PayTransfer(cp_new, max_move);
 
			}
 
			cp->count -= count;
 

	
 
			count = 0;
 
			dest->Append(cp_new);
 
		}
 
		cp->count -= max_move;
 

	
 
		max_move = 0;
 
	}
 

	
 
	bool remaining = !this->packets.empty();
 

	
 
	if (mta == MTA_FINAL_DELIVERY && !tmp.Empty()) {
 
		/* There are some packets that could not be delivered at the station, put them back */
 
		tmp.MoveTo(this, UINT_MAX, MTA_UNLOAD, NULL);
 
		tmp.packets.clear();
 
	}
 

	
 
	if (dest != NULL) dest->InvalidateCache();
 
	this->InvalidateCache();
 

	
 
	return remaining;
 
	return it != packets.end();
 
}
 

	
 
void CargoList::InvalidateCache()
 
{
 
	this->count = 0;
 
	this->feeder_share = 0;
 
	this->cargo_days_in_transit = 0;
 

	
 
	for (List::const_iterator it = this->packets.begin(); it != this->packets.end(); it++) {
 
		this->AddToCache(*it);
 
	}
 
}
src/cargopacket.h
Show inline comments
 
@@ -257,27 +257,27 @@ public:
 
	/**
 
	 * Appends the given cargo packet
 
	 * @warning After appending this packet may not exist anymore!
 
	 * @note Do not use the cargo packet anymore after it has been appended to this CargoList!
 
	 * @param cp the cargo packet to add
 
	 * @pre cp != NULL
 
	 */
 
	void Append(CargoPacket *cp);
 

	
 
	/**
 
	 * Truncates the cargo in this list to the given amount. It leaves the
 
	 * first count cargo entities and removes the rest.
 
	 * @param count the maximum amount of entities to be in the list after the command
 
	 * @param max_remaining the maximum amount of entities to be in the list after the command
 
	 */
 
	void Truncate(uint count);
 
	void Truncate(uint max_remaining);
 

	
 
	/**
 
	 * Moves the given amount of cargo to another list.
 
	 * Depending on the value of mta the side effects of this function differ:
 
	 *  - MTA_FINAL_DELIVERY: destroys the packets that do not originate from a specific station
 
	 *  - MTA_CARGO_LOAD:     sets the loaded_at_xy value of the moved packets
 
	 *  - MTA_TRANSFER:       just move without side effects
 
	 *  - MTA_UNLOAD:         just move without side effects
 
	 * @param dest  the destination to move the cargo to
 
	 * @param count the amount of cargo entities to move
 
	 * @param mta   how to handle the moving (side effects)
 
	 * @param data  Depending on mta the data of this variable differs:
0 comments (0 inline, 0 general)