# cargopacket.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "station_base.h"
    00014 #include "core/pool_func.hpp"
    00015 #include "core/random_func.hpp"
    00016 #include "economy_base.h"
    00017
    00018 /* Initialize the cargopacket-pool */
    00019 CargoPacketPool _cargopacket_pool("CargoPacket");
    00020 INSTANTIATE_POOL_METHODS(CargoPacket)
    00021
    00022
    00025 CargoPacket::CargoPacket()
    00026 {
    00027   this->source_type = ST_INDUSTRY;
    00028   this->source_id   = INVALID_SOURCE;
    00029 }
    00030
    00042 CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) :
    00043     feeder_share(0),
    00044     count(count),
    00045     days_in_transit(0),
    00046     source_id(source_id),
    00047     source(source),
    00048     source_xy(source_xy),
    00049     loaded_at_xy(0)
    00050 {
    00051   assert(count != 0);
    00052   this->source_type  = source_type;
    00053 }
    00054
    00069 CargoPacket::CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share, SourceType source_type, SourceID source_id) :
    00070     feeder_share(feeder_share),
    00071     count(count),
    00072     days_in_transit(days_in_transit),
    00073     source_id(source_id),
    00074     source(source),
    00075     source_xy(source_xy),
    00076     loaded_at_xy(loaded_at_xy)
    00077 {
    00078   assert(count != 0);
    00079   this->source_type = source_type;
    00080 }
    00081
    00087 FORCEINLINE CargoPacket *CargoPacket::Split(uint new_size)
    00088 {
    00089   if (!CargoPacket::CanAllocateItem()) return NULL;
    00090
    00091   Money fs = this->feeder_share * new_size / static_cast<uint>(this->count);
    00092   CargoPacket *cp_new = new CargoPacket(new_size, this->days_in_transit, this->source, this->source_xy, this->loaded_at_xy, fs, this->source_type, this->source_id);
    00093   this->feeder_share -= fs;
    00094   this->count -= new_size;
    00095   return cp_new;
    00096 }
    00097
    00102 FORCEINLINE void CargoPacket::Merge(CargoPacket *cp)
    00103 {
    00104   this->count += cp->count;
    00105   this->feeder_share += cp->feeder_share;
    00106   delete cp;
    00107 }
    00108
    00114 /* static */ void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
    00115 {
    00116   CargoPacket *cp;
    00117   FOR_ALL_CARGOPACKETS(cp) {
    00118     if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
    00119   }
    00120 }
    00121
    00126 /* static */ void CargoPacket::InvalidateAllFrom(StationID sid)
    00127 {
    00128   CargoPacket *cp;
    00129   FOR_ALL_CARGOPACKETS(cp) {
    00130     if (cp->source == sid) cp->source = INVALID_STATION;
    00131   }
    00132 }
    00133
    00134 /*
    00135  *
    00136  * Cargo list implementation.
    00137  *
    00138  */
    00139
    00143 template <class Tinst, class Tcont>
    00144 CargoList<Tinst, Tcont>::~CargoList()
    00145 {
    00146   for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
    00147     delete *it;
    00148   }
    00149 }
    00150
    00155 template <class Tinst, class Tcont>
    00156 void CargoList<Tinst,Tcont>::OnCleanPool()
    00157 {
    00158   this->packets.clear();
    00159 }
    00160
    00166 template <class Tinst, class Tcont>
    00167 void CargoList<Tinst, Tcont>::RemoveFromCache(const CargoPacket *cp)
    00168 {
    00169   this->count                 -= cp->count;
    00170   this->cargo_days_in_transit -= cp->days_in_transit * cp->count;
    00171 }
    00172
    00178 template <class Tinst, class Tcont>
    00179 void CargoList<Tinst, Tcont>::AddToCache(const CargoPacket *cp)
    00180 {
    00181   this->count                 += cp->count;
    00182   this->cargo_days_in_transit += cp->days_in_transit * cp->count;
    00183 }
    00184
    00195 void VehicleCargoList::Append(CargoPacket *cp, bool update_cache)
    00196 {
    00197   assert(cp != NULL);
    00198
    00199   if (update_cache) this->AddToCache(cp);
    00200   for (CargoPacketList::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
    00201     CargoPacket *icp = *it;
    00202     if (VehicleCargoList::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
    00203       icp->Merge(cp);
    00204       return;
    00205     }
    00206   }
    00207
    00208   /* The packet could not be merged with another one. */
    00209   this->packets.push_back(cp);
    00210 }
    00211
    00217 template <class Tinst, class Tcont>
    00218 void CargoList<Tinst, Tcont>::Truncate(uint max_remaining)
    00219 {
    00220   for (Iterator it(packets.begin()); it != packets.end(); /* Done during loop. */) {
    00221     CargoPacket *cp = *it;
    00222     if (max_remaining == 0) {
    00223       /* Nothing should remain, just remove the packets. */
    00224       this->packets.erase(it++);
    00225       static_cast<Tinst *>(this)->RemoveFromCache(cp);
    00226       delete cp;
    00227       continue;
    00228     }
    00229
    00230     uint local_count = cp->count;
    00231     if (local_count > max_remaining) {
    00232       uint diff = local_count - max_remaining;
    00233       this->count -= diff;
    00234       this->cargo_days_in_transit -= cp->days_in_transit * diff;
    00235       cp->count = max_remaining;
    00236       max_remaining = 0;
    00237     } else {
    00238       max_remaining -= local_count;
    00239     }
    00240     ++it;
    00241   }
    00242 }
    00243
    00248 void VehicleCargoList::Reserve(CargoPacket *cp)
    00249 {
    00250   assert(cp != NULL);
    00251   this->AddToCache(cp);
    00252   this->reserved_count += cp->count;
    00253   this->reserved.push_back(cp);
    00254 }
    00255
    00261 void VehicleCargoList::Unreserve(StationID next, StationCargoList *dest)
    00262 {
    00263   Iterator it(this->reserved.begin());
    00264   while (it != this->reserved.end()) {
    00265     CargoPacket *cp = *it;
    00266     this->RemoveFromCache(cp);
    00267     this->reserved_count -= cp->count;
    00268     dest->Append(next, cp);
    00269     this->reserved.erase(it++);
    00270   }
    00271 }
    00272
    00278 uint VehicleCargoList::LoadReserved(uint max_move)
    00279 {
    00280   uint orig_max = max_move;
    00281   Iterator it(this->reserved.begin());
    00282   while (it != this->reserved.end() && max_move > 0) {
    00283     CargoPacket *cp = *it;
    00284     if (cp->count <= max_move) {
    00285       /* Can move the complete packet. */
    00286       max_move -= cp->count;
    00287       this->reserved.erase(it++);
    00288       this->reserved_count -= cp->count;
    00289       this->Append(cp, false);
    00290     } else if (CargoPacket::CanAllocateItem()) {
    00291       cp->count -= max_move;
    00292       CargoPacket *cp_new = new CargoPacket(max_move, cp->days_in_transit, cp->source, cp->source_xy, cp->loaded_at_xy, 0, cp->source_type, cp->source_id);
    00293       this->Append(cp_new, false);
    00294       this->reserved_count -= max_move;
    00295       max_move = 0;
    00296     }
    00297   }
    00298   return orig_max - max_move;
    00299 }
    00300
    00311 template<class Tinst, class Tcont>
    00312 uint CargoList<Tinst, Tcont>::MovePacket(VehicleCargoList *dest, Iterator &it, uint cap, TileIndex load_place, bool reserve)
    00313 {
    00314   CargoPacket *packet = this->RemovePacket(it, cap, load_place);
    00315   uint ret = packet->count;
    00316   if (reserve) {
    00317     dest->Reserve(packet);
    00318   } else {
    00319     dest->Append(packet);
    00320   }
    00321   return ret;
    00322 }
    00323
    00333 template<class Tinst, class Tcont>
    00334 uint CargoList<Tinst, Tcont>::MovePacket(StationCargoList *dest, StationID next, Iterator &it, uint cap)
    00335 {
    00336   CargoPacket *packet = this->RemovePacket(it, cap);
    00337   uint ret = packet->count;
    00338   dest->Append(next, packet);
    00339   return ret;
    00340 }
    00341
    00351 template<class Tinst, class Tcont>
    00352 CargoPacket *CargoList<Tinst, Tcont>::RemovePacket(Iterator &it, uint cap, TileIndex load_place)
    00353 {
    00354   CargoPacket *packet = *it;
    00355   /* Load the packet if possible. */
    00356   if (packet->count > cap) {
    00357     /* Packet needs to be split. */
    00358     packet = packet->Split(cap);
    00359
    00360     /* We could not allocate a CargoPacket? Is the map that full?
    00361      * Just remove the whole packet and drop some cargo then.
    00362      */
    00363     if (packet == NULL) {
    00364       packet = *it;
    00365       uint dropped = packet->count - cap;
    00366       this->count -= dropped;
    00367       this->cargo_days_in_transit -= dropped * packet->days_in_transit;
    00368       packet->count = cap;
    00369       this->packets.erase(it++);
    00370     } else {
    00371       assert(packet->count == cap);
    00372       ++it;
    00373     }
    00374   } else {
    00375     this->packets.erase(it++);
    00376   }
    00377   static_cast<Tinst *>(this)->RemoveFromCache(packet);
    00378   if (load_place != INVALID_TILE) {
    00379     packet->loaded_at_xy = load_place;
    00380   }
    00381   return packet;
    00382 }
    00383
    00387 template <class Tinst, class Tcont>
    00388 void CargoList<Tinst, Tcont>::InvalidateCache()
    00389 {
    00390   this->count = 0;
    00391   this->cargo_days_in_transit = 0;
    00392
    00393   for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
    00394     static_cast<Tinst *>(this)->AddToCache(*it);
    00395   }
    00396 }
    00397
    00401 VehicleCargoList::~VehicleCargoList()
    00402 {
    00403   for (Iterator it(this->reserved.begin()); it != this->reserved.end(); ++it) {
    00404     delete *it;
    00405   }
    00406 }
    00407
    00416 uint VehicleCargoList::DeliverPacket(Iterator &it, uint cap, CargoPayment *payment)
    00417 {
    00418   CargoPacket *p = *it;
    00419   uint unloaded = 0;
    00420   if (p->count <= cap) {
    00421     payment->PayFinalDelivery(p, p->count);
    00422     this->packets.erase(it++);
    00423     this->RemoveFromCache(p);
    00424     unloaded = p->count;
    00425     delete p;
    00426   } else {
    00427     payment->PayFinalDelivery(p, cap);
    00428     this->count -= cap;
    00429     this->cargo_days_in_transit -= cap * p->days_in_transit;
    00430     this->feeder_share -= p->feeder_share;
    00431     p->feeder_share = 0;
    00432     p->count -= cap;
    00433     unloaded = cap;
    00434     ++it;
    00435   }
    00436   return unloaded;
    00437 }
    00438
    00445 uint VehicleCargoList::KeepPacket(Iterator &it)
    00446 {
    00447   CargoPacket *cp = *it;
    00448   this->reserved.push_back(cp);
    00449   this->reserved_count += cp->count;
    00450   this->packets.erase(it++);
    00451   return cp->count;
    00452 }
    00453
    00465 uint VehicleCargoList::TransferPacket(Iterator &it, uint cap, StationCargoList *dest, CargoPayment *payment, StationID next)
    00466 {
    00467   CargoPacket *cp = this->RemovePacket(it, cap);
    00468   cp->feeder_share += payment->PayTransfer(cp, cp->count);
    00469   uint ret = cp->count;
    00470   dest->Append(next, cp);
    00471   return ret;
    00472 }
    00473
    00483 UnloadType StationCargoList::WillUnloadOld(byte flags, StationID source)
    00484 {
    00485   /* Try to unload cargo. */
    00486   bool move = (flags & (UL_DELIVER | UL_ACCEPTED | UL_TRANSFER)) != 0;
    00487   /* Try to deliver cargo if unloading. */
    00488   bool deliver = (flags & UL_ACCEPTED) && !(flags & UL_TRANSFER) && (source != this->station->index);
    00489   /* Transfer cargo if delivery was unsuccessful. */
    00490   bool transfer = (flags & (UL_TRANSFER | UL_DELIVER)) != 0;
    00491   if (move) {
    00492     if(deliver) {
    00493       return UL_DELIVER;
    00494     } else if (transfer) {
    00495       return UL_TRANSFER;
    00496     } else {
    00497       /* This case is for (non-)delivery to the source station without special flags.
    00498        * Like the code in MoveTo did, we keep the packet in this case.
    00499        */
    00500       return UL_KEEP;
    00501     }
    00502   } else {
    00503     return UL_KEEP;
    00504   }
    00505 }
    00506
    00520 UnloadType StationCargoList::WillUnloadCargoDist(byte flags, StationID next, StationID via, StationID source)
    00521 {
    00522   if (via == this->station->index) {
    00523     /* This is the final destination, deliver ... */
    00524     if (flags & UL_TRANSFER) {
    00525       /* .. except if explicitly told not to do so ... */
    00526       return UL_TRANSFER;
    00527     } else if (flags & UL_ACCEPTED) {
    00528       return UL_DELIVER;
    00529     } else if (flags & UL_DELIVER) {
    00530       /* .. or if the station suddenly doesn't accept our cargo, but we have an explicit deliver order... */
    00531       return UL_TRANSFER;
    00532     } else {
    00533       /* .. or else if it doesn't accept. */
    00534       return UL_KEEP;
    00535     }
    00536   } else {
    00537     /* Packet has to travel on, find out if it can stay on board. */
    00538     if (flags & UL_DELIVER) {
    00539       /* Order overrides cargodist:
    00540        * play by the old loading rules here as player is interfering with cargodist.
    00541        * Try to deliver, as move has been forced upon us. */
    00542       if ((flags & UL_ACCEPTED) && !(flags & UL_TRANSFER) && source != this->station->index) {
    00543         return UL_DELIVER;
    00544       } else {
    00545         /* Transfer cargo, as delivering didn't work. */
    00546         return UL_TRANSFER;
    00547       }
    00548     } else if (flags & UL_TRANSFER) {
    00549       /* Transfer forced. */
    00550       return UL_TRANSFER;
    00551     } else if (next == via && next != INVALID_STATION) {
    00552       /* Vehicle goes to the packet's next hop or has nondeterministic order: keep the packet. */
    00553       return UL_KEEP;
    00554     } else {
    00555       /* Vehicle goes somewhere else, transfer the packet. */
    00556       return UL_TRANSFER;
    00557     }
    00558   }
    00559 }
    00560
    00567 void VehicleCargoList::SwapReserved()
    00568 {
    00569   assert(this->packets.empty());
    00570   this->packets.swap(this->reserved);
    00571   this->reserved_count = 0;
    00572 }
    00573
    00595 uint StationCargoList::TakeFrom(VehicleCargoList *source, uint max_unload, OrderUnloadFlags order_flags, StationID next, bool has_stopped, CargoPayment *payment)
    00596 {
    00597   uint remaining_unload = max_unload;
    00598   uint unloaded;
    00599   byte flags = this->GetUnloadFlags(order_flags);
    00600   GoodsEntry *dest = &this->station->goods[this->cargo];
    00601   UnloadType action;
    00602
    00603   for (VehicleCargoList::Iterator c = source->packets.begin(); c != source->packets.end() && remaining_unload > 0;) {
    00604     StationID cargo_source = (*c)->source;
    00605     FlowStatSet &flows = dest->flows[cargo_source];
    00606     FlowStatSet::iterator begin = flows.begin();
    00607     StationID via = (begin != flows.end() ? begin->Via() : INVALID_STATION);
    00608     if (via != INVALID_STATION) {
    00609       /* Use cargodist unloading. */
    00610       action = this->WillUnloadCargoDist(flags, next, via, cargo_source);
    00611     } else {
    00612       /* There is no plan: use normal unloading. */
    00613       action = WillUnloadOld(flags, cargo_source);
    00614     }
    00615
    00616     switch(action) {
    00617       case UL_DELIVER:
    00618         unloaded = source->DeliverPacket(c, remaining_unload, payment);
    00619         if (via != INVALID_STATION) {
    00620           if (via == this->station->index) {
    00621             dest->UpdateFlowStats(flows, begin, unloaded);
    00622           } else {
    00623             dest->UpdateFlowStats(flows, unloaded, this->station->index);
    00624           }
    00625         }
    00626         remaining_unload -= unloaded;
    00627         break;
    00628       case UL_TRANSFER:
    00629         /* TransferPacket may split the packet and return the transferred part. */
    00630         if (via == this->station->index) {
    00631           via = (++begin != flows.end()) ? begin->Via() : INVALID_STATION;
    00632         }
    00633         unloaded = source->TransferPacket(c, remaining_unload, this, payment, via);
    00634         if (via != INVALID_STATION) {
    00635           dest->UpdateFlowStats(flows, begin, unloaded);
    00636         }
    00637         remaining_unload -= unloaded;
    00638         break;
    00639       case UL_KEEP:
    00640         unloaded = source->KeepPacket(c);
    00641         if (via != INVALID_STATION && next != INVALID_STATION && !has_stopped) {
    00642           if (via == next) {
    00643             dest->UpdateFlowStats(flows, begin, unloaded);
    00644           } else {
    00645             dest->UpdateFlowStats(flows, unloaded, next);
    00646           }
    00647         }
    00648         break;
    00649       default:
    00650         NOT_REACHED();
    00651     }
    00652   }
    00653   return max_unload - remaining_unload;
    00654 }
    00655
    00659 void VehicleCargoList::OnCleanPool()
    00660 {
    00661   this->reserved.clear();
    00662   this->Parent::OnCleanPool();
    00663 }
    00664
    00670 void VehicleCargoList::RemoveFromCache(const CargoPacket *cp)
    00671 {
    00672   this->feeder_share -= cp->feeder_share;
    00673   this->Parent::RemoveFromCache(cp);
    00674 }
    00675
    00681 void VehicleCargoList::AddToCache(const CargoPacket *cp)
    00682 {
    00683   this->feeder_share += cp->feeder_share;
    00684   this->Parent::AddToCache(cp);
    00685 }
    00686
    00693 uint VehicleCargoList::MoveTo(VehicleCargoList *dest, uint cap)
    00694 {
    00695   uint orig_cap = cap;
    00696   Iterator it = packets.begin();
    00697   while (it != packets.end() && cap > 0) {
    00698     cap -= MovePacket(dest, it, cap);
    00699   }
    00700   return orig_cap - cap;
    00701 }
    00702
    00706 void VehicleCargoList::AgeCargo()
    00707 {
    00708   for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
    00709     CargoPacket *cp = *it;
    00710     /* If we're at the maximum, then we can't increase no more. */
    00711     if (cp->days_in_transit == 0xFF) continue;
    00712
    00713     cp->days_in_transit++;
    00714     this->cargo_days_in_transit += cp->count;
    00715   }
    00716 }
    00717
    00718 /*
    00719  *
    00720  * Station cargo list implementation.
    00721  *
    00722  */
    00723
    00729 FORCEINLINE byte StationCargoList::GetUnloadFlags(OrderUnloadFlags order_flags)
    00730 {
    00731   byte flags = 0;
    00732   if (HasBit(this->station->goods[this->cargo].acceptance_pickup, GoodsEntry::GES_ACCEPTANCE)) {
    00733     flags |= UL_ACCEPTED;
    00734   }
    00735   if (order_flags & OUFB_UNLOAD) {
    00736     flags |= UL_DELIVER;
    00737   }
    00738   if (order_flags & OUFB_TRANSFER) {
    00739     flags |= UL_TRANSFER;
    00740   }
    00741   return flags;
    00742 }
    00743
    00752 void StationCargoList::Append(StationID next, CargoPacket *cp)
    00753 {
    00754   assert(cp != NULL);
    00755   this->AddToCache(cp);
    00756
    00757   StationCargoPacketMap::List &list = this->packets[next];
    00758
    00759   for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin()); it != list.rend(); it++) {
    00760     CargoPacket *icp = *it;
    00761     if (StationCargoList::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
    00762       icp->Merge(cp);
    00763       return;
    00764     }
    00765   }
    00766
    00767   /* The packet could not be merged with another one. */
    00768   list.push_back(cp);
    00769 }
    00770
    00780 uint StationCargoList::MovePackets(VehicleCargoList *dest, uint cap, Iterator begin, Iterator end, bool reserve)
    00781 {
    00782   uint orig_cap = cap;
    00783   while (begin != end && cap > 0) {
    00784     cap -= this->MovePacket(dest, begin, cap, this->station->xy, reserve);
    00785   }
    00786   return orig_cap - cap;
    00787 }
    00788
    00797 uint StationCargoList::MoveTo(VehicleCargoList *dest, uint cap, StationID next, bool reserve)
    00798 {
    00799   uint orig_cap = cap;
    00800   std::pair<Iterator, Iterator> bounds(this->packets.equal_range(next));
    00801   cap -= this->MovePackets(dest, cap, bounds.first, bounds.second, reserve);
    00802   if (next != INVALID_STATION && cap > 0) {
    00803     bounds = this->packets.equal_range(INVALID_STATION);
    00804     cap -= this->MovePackets(dest, cap, bounds.first, bounds.second, reserve);
    00805   }
    00806   return orig_cap - cap;
    00807 }
    00808
    00813 void StationCargoList::RerouteStalePackets(StationID to)
    00814 {
    00815   std::pair<Iterator, Iterator> range(this->packets.equal_range(to));
    00816   for (Iterator it(range.first); it != range.second && it.GetKey() == to;) {
    00817     CargoPacket *packet = *it;
    00818     this->packets.erase(it++);
    00819     StationID next = this->station->goods[this->cargo].UpdateFlowStatsTransfer(packet->source, packet->count, this->station->index);
    00820     assert(next != to);
    00821
    00822     /* Legal, as insert doesn't invalidate iterators in the MultiMap, however
    00823      * this might insert the packet between range.first and range.second (which might be end())
    00824      * This is why we check for GetKey above to avoid infinite loops.
    00825      */
    00826     this->packets.Insert(next, packet);
    00827   }
    00828 }
    00829
    00837 void StationCargoList::CountAndTruncate(uint max_remaining, StationCargoAmountMap &cargo_per_source)
    00838 {
    00839   uint prev_count = this->count;
    00840   uint loop = 0;
    00841   while (this->count > max_remaining) {
    00842     for (Iterator it(this->packets.begin()); it != this->packets.end();) {
    00843       CargoPacket *packet = *it;
    00844       if (loop == 0) cargo_per_source[packet->source] += packet->count;
    00845
    00846       if (RandomRange(prev_count) < max_remaining) {
    00847         ++it;
    00848         continue;
    00849       }
    00850
    00851       uint diff = this->count - max_remaining;
    00852       if (packet->count > diff) {
    00853         packet->count -= diff;
    00854         this->count = max_remaining;
    00855         this->cargo_days_in_transit -= packet->days_in_transit * diff;
    00856         if (loop > 0) {
    00857           return;
    00858         } else {
    00859           ++it;
    00860         }
    00861       } else {
    00862         this->packets.erase(it++);
    00863         this->RemoveFromCache(packet);
    00864         delete packet;
    00865       }
    00866     }
    00867     loop++;
    00868   }
    00869 }
    00870
    00872 void VehicleCargoList::InvalidateCache()
    00873 {
    00874   this->feeder_share = 0;
    00875   this->reserved_count = 0;
    00876   this->Parent::InvalidateCache();
    00877   for (ConstIterator it(this->reserved.begin()); it != this->reserved.end(); it++) {
    00878     this->AddToCache(*it);
    00879     this->reserved_count += (*it)->count;
    00880   }
    00881 }
    00882
    00888 void StationCargoList::AssignTo(Station *station, CargoID cargo)
    00889 {
    00890   assert(this->station == NULL);
    00891   assert(station != NULL && cargo != INVALID_CARGO);
    00892   this->station = station;
    00893   this->cargo = cargo;
    00894 }
    00895
    00897 template class CargoList<VehicleCargoList, CargoPacketList>;
    00898 template class CargoList<StationCargoList, StationCargoPacketMap>;