From 0246d59c8d3c658305dfbb673930c99ee9055805 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 30 Sep 2019 10:26:07 +0100 Subject: [PATCH] FlowStat: Replace btree_map with flat map which is inlined in small case Inline storage for size <= 2 Size = 1 is ~90% Size = 2 is ~9% Size >=3 is ~1% and gets a separate allocation --- src/cargopacket.cpp | 4 +- src/linkgraph/linkgraphjob.cpp | 4 +- src/linkgraph/mcf.cpp | 12 +- src/saveload/station_sl.cpp | 7 +- src/script/api/script_stationlist.cpp | 10 +- src/station_base.h | 180 +++++++++++++++++++--- src/station_cmd.cpp | 210 ++++++++++++-------------- src/station_gui.cpp | 9 +- 8 files changed, 275 insertions(+), 161 deletions(-) diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index 2c66975787..e0f9fea9af 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -663,10 +663,10 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID FlowStat new_shares = *flow_it; new_shares.ChangeShare(current_station, INT_MIN); StationIDStack excluded = next_station; - while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) { + while (!excluded.IsEmpty() && !new_shares.empty()) { new_shares.ChangeShare(excluded.Pop(), INT_MIN); } - if (new_shares.GetShares()->empty()) { + if (new_shares.empty()) { cargo_next = INVALID_STATION; } else { cargo_next = new_shares.GetVia(); diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index c6db2adbef..21c9712097 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -155,8 +155,8 @@ void LinkGraphJob::FinaliseJob() FlowStat shares(INVALID_STATION, INVALID_STATION, 1); it->SwapShares(shares); it = ge.flows.erase(it); - for (FlowStat::SharesMap::const_iterator shares_it(shares.GetShares()->begin()); - shares_it != shares.GetShares()->end(); ++shares_it) { + for (FlowStat::const_iterator shares_it(shares.begin()); + shares_it != shares.end(); ++shares_it) { RerouteCargo(st, this->Cargo(), shares_it->second, st->index); } } diff --git a/src/linkgraph/mcf.cpp b/src/linkgraph/mcf.cpp index d87b3fd9b2..0c03b930f6 100644 --- a/src/linkgraph/mcf.cpp +++ b/src/linkgraph/mcf.cpp @@ -156,10 +156,10 @@ private: std::vector station_to_node; /** Current iterator in the shares map. */ - FlowStat::SharesMap::const_iterator it; + FlowStat::const_iterator it; /** End of the shares map. */ - FlowStat::SharesMap::const_iterator end; + FlowStat::const_iterator end; public: /** @@ -187,11 +187,11 @@ public: const FlowStatMap &flows = this->job[node].Flows(); FlowStatMap::const_iterator it = flows.find(this->job[source].Station()); if (it != flows.end()) { - this->it = it->GetShares()->begin(); - this->end = it->GetShares()->end(); + this->it = it->begin(); + this->end = it->end(); } else { - this->it = FlowStat::empty_sharesmap.begin(); - this->end = FlowStat::empty_sharesmap.end(); + this->it = nullptr; + this->end = nullptr; } } diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 559c140e13..99d4e7c85f 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -523,15 +523,16 @@ static void RealSave_STNN(BaseStation *bst) _num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize(); _num_flows = 0; for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) { - _num_flows += (uint32)it->GetShares()->size(); + _num_flows += (uint32)it->size(); } SlObjectSaveFiltered(&st->goods[i], _filtered_goods_desc.data()); for (FlowStatMap::const_iterator outer_it(st->goods[i].flows.begin()); outer_it != st->goods[i].flows.end(); ++outer_it) { - const FlowStat::SharesMap *shares = outer_it->GetShares(); uint32 sum_shares = 0; FlowSaveLoad flow; flow.source = outer_it->GetOrigin(); - for (FlowStat::SharesMap::const_iterator inner_it(shares->begin()); inner_it != shares->end(); ++inner_it) { + FlowStat::const_iterator inner_it(outer_it->begin()); + const FlowStat::const_iterator end(outer_it->end()); + for (; inner_it != end; ++inner_it) { flow.via = inner_it->second; flow.share = inner_it->first - sum_shares; flow.restricted = inner_it->first > outer_it->GetUnrestricted(); diff --git a/src/script/api/script_stationlist.cpp b/src/script/api/script_stationlist.cpp index 2174ae66b4..f8871ad43c 100644 --- a/src/script/api/script_stationlist.cpp +++ b/src/script/api/script_stationlist.cpp @@ -195,10 +195,9 @@ void ScriptStationList_CargoPlanned::Add(StationID station_id, CargoID cargo, St FlowStatMap::const_iterator iter = collector.GE()->flows.begin(); FlowStatMap::const_iterator end = collector.GE()->flows.end(); for (; iter != end; ++iter) { - const FlowStat::SharesMap *shares = iter->GetShares(); uint prev = 0; - for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin(); - flow_iter != shares->end(); ++flow_iter) { + for (FlowStat::const_iterator flow_iter = iter->begin(); + flow_iter != iter->end(); ++flow_iter) { collector.Update(iter->GetOrigin(), flow_iter->second, flow_iter->first - prev); prev = flow_iter->first; } @@ -265,10 +264,9 @@ ScriptStationList_CargoPlannedFromByVia::ScriptStationList_CargoPlannedFromByVia FlowStatMap::const_iterator iter = collector.GE()->flows.find(from); if (iter == collector.GE()->flows.end()) return; - const FlowStat::SharesMap *shares = iter->GetShares(); uint prev = 0; - for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin(); - flow_iter != shares->end(); ++flow_iter) { + for (FlowStat::const_iterator flow_iter = iter->begin(); + flow_iter != iter->end(); ++flow_iter) { collector.Update(iter->GetOrigin(), flow_iter->second, flow_iter->first - prev); prev = flow_iter->first; } diff --git a/src/station_base.h b/src/station_base.h index 27907c12c5..a8e9ae9f8a 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -22,10 +22,12 @@ #include "3rdparty/cpp-btree/btree_map.h" #include "3rdparty/cpp-btree/btree_set.h" #include "bitmap_type.h" +#include "core/endian_type.hpp" #include #include #include #include +#include typedef Pool StationPool; extern StationPool _station_pool; @@ -44,9 +46,28 @@ class FlowStatMap; class FlowStat { friend FlowStatMap; public: - typedef btree::btree_map SharesMap; + struct ShareEntry { +#if OTTD_ALIGNMENT == 0 + unaligned_uint32 first; +#else + uint32 first; +#endif + StationID second; + }; + static_assert(sizeof(ShareEntry) == 6, ""); + + friend bool operator<(const ShareEntry &a, const ShareEntry &b) noexcept + { + return a.first < b.first; + } + + friend bool operator<(uint a, const ShareEntry &b) noexcept + { + return a < b.first; + } - static const SharesMap empty_sharesmap; + typedef ShareEntry* iterator; + typedef const ShareEntry* const_iterator; /** * Invalid constructor. This can't be called as a FlowStat must not be @@ -65,11 +86,92 @@ public: inline FlowStat(StationID origin, StationID via, uint flow, bool restricted = false) { assert(flow > 0); - this->shares[flow] = via; + this->storage.inline_shares[0].first = flow; + this->storage.inline_shares[0].second = via; this->unrestricted = restricted ? 0 : flow; + this->count = 1; this->origin = origin; } +private: + inline bool inline_mode() const + { + return this->count <= 2; + } + + inline const ShareEntry *data() const + { + return this->inline_mode() ? this->storage.inline_shares : this->storage.ptr_shares.buffer; + } + + inline ShareEntry *data() + { + return const_cast(const_cast(this)->data()); + } + + inline void clear() + { + if (!inline_mode()) { + free(this->storage.ptr_shares.buffer); + } + this->count = 0; + } + + iterator erase_item(iterator iter, uint flow_reduction); + + inline void CopyCommon(const FlowStat &other) + { + this->count = other.count; + if (!other.inline_mode()) { + this->storage.ptr_shares.elem_capacity = other.storage.ptr_shares.elem_capacity; + this->storage.ptr_shares.buffer = MallocT(other.storage.ptr_shares.elem_capacity); + } + MemCpyT(this->data(), other.data(), this->count); + this->unrestricted = other.unrestricted; + this->origin = other.origin; + } + +public: + inline FlowStat(const FlowStat &other) + { + this->CopyCommon(other); + } + + inline FlowStat(FlowStat &&other) noexcept + { + this->count = 0; + this->SwapShares(other); + this->origin = other.origin; + } + + inline ~FlowStat() + { + this->clear(); + } + + inline FlowStat &operator=(const FlowStat &other) + { + this->clear(); + this->CopyCommon(other); + return *this; + } + + inline FlowStat &operator=(FlowStat &&other) noexcept + { + this->SwapShares(other); + this->origin = other.origin; + return *this; + } + + inline size_t size() const { return this->count; } + inline bool empty() const { return this->count == 0; } + inline iterator begin() { return this->data(); } + inline const_iterator begin() const { return this->data(); } + inline iterator end() { return this->data() + this->count; } + inline const_iterator end() const { return this->data() + this->count; } + inline iterator upper_bound(uint32 key) { return std::upper_bound(this->begin(), this->end(), key); } + inline const_iterator upper_bound(uint32 key) const { return std::upper_bound(this->begin(), this->end(), key); } + /** * Add some flow to the end of the shares map. Only do that if you know * that the station isn't in the map yet. Anything else may lead to @@ -81,8 +183,26 @@ public: inline void AppendShare(StationID st, uint flow, bool restricted = false) { assert(flow > 0); - uint32 key = (--this->shares.end())->first + flow; - this->shares.insert(this->shares.end(), std::make_pair(key, st)); + uint32 key = this->GetLastKey() + flow; + if (unlikely(this->count >= 2)) { + if (this->count == 2) { + // convert inline buffer to ptr + ShareEntry *ptr = MallocT(4); + ptr[0] = this->storage.inline_shares[0]; + ptr[1] = this->storage.inline_shares[1]; + this->storage.ptr_shares.buffer = ptr; + this->storage.ptr_shares.elem_capacity = 4; + } else if (this->count == this->storage.ptr_shares.elem_capacity) { + // grow buffer + uint16 new_size = this->storage.ptr_shares.elem_capacity * 2; + this->storage.ptr_shares.buffer = ReallocT(this->storage.ptr_shares.buffer, new_size); + this->storage.ptr_shares.elem_capacity = new_size; + } + this->storage.ptr_shares.buffer[this->count] = { key, st }; + } else { + this->storage.inline_shares[this->count] = { key, st }; + } + this->count++; if (!restricted) this->unrestricted += flow; } @@ -96,13 +216,6 @@ public: void ScaleToMonthly(uint runtime); - /** - * Get the actual shares as a const pointer so that they can be iterated - * over. - * @return Actual shares. - */ - inline const SharesMap *GetShares() const { return &this->shares; } - /** * Return total amount of unrestricted shares. * @return Amount of unrestricted shares. @@ -116,8 +229,9 @@ public: */ inline void SwapShares(FlowStat &other) { - this->shares.swap(other.shares); - Swap(this->unrestricted, other.unrestricted); + std::swap(this->storage, other.storage); + std::swap(this->unrestricted, other.unrestricted); + std::swap(this->count, other.count); } /** @@ -130,10 +244,10 @@ public: */ inline StationID GetViaWithRestricted(bool &is_restricted) const { - assert(!this->shares.empty()); - uint rand = RandomRange((--this->shares.end())->first); + assert(!this->empty()); + uint rand = RandomRange(this->GetLastKey()); is_restricted = rand >= this->unrestricted; - return this->shares.upper_bound(rand)->second; + return this->upper_bound(rand)->second; } /** @@ -145,9 +259,9 @@ public: */ inline StationID GetVia() const { - assert(!this->shares.empty()); + assert(!this->empty()); return this->unrestricted > 0 ? - this->shares.upper_bound(RandomRange(this->unrestricted))->second : + this->upper_bound(RandomRange(this->unrestricted))->second : INVALID_STATION; } @@ -161,11 +275,36 @@ public: } private: - SharesMap shares; ///< Shares of flow to be sent via specified station (or consumed locally). + uint32 GetLastKey() const + { + return this->data()[this->count - 1].first; + } + + struct ptr_buffer { + ShareEntry *buffer; + uint16 elem_capacity; + } +#if OTTD_ALIGNMENT == 0 && (defined(__GNUC__) || defined(__clang__)) + __attribute__((packed, aligned(4))) +#endif + ; + union storage_union { + ShareEntry inline_shares[2]; ///< Small buffer optimisation: size = 1 is ~90%, size = 2 is ~9%, size >= 3 is ~1% + ptr_buffer ptr_shares; + + // Actual construction/destruction done by class FlowStat + storage_union() {} + ~storage_union() {} + }; + storage_union storage; ///< Shares of flow to be sent via specified station (or consumed locally). uint unrestricted; ///< Limit for unrestricted shares. + uint16 count; StationID origin; }; static_assert(std::is_nothrow_move_constructible::value, "FlowStat must be nothrow move constructible"); +#if OTTD_ALIGNMENT == 0 && (defined(__GNUC__) || defined(__clang__)) +static_assert(sizeof(FlowStat) == 20, ""); +#endif template class FlowStatMapIterator @@ -224,7 +363,6 @@ public: void PassOnFlow(StationID origin, StationID via, uint amount); StationIDStack DeleteFlows(StationID via); void RestrictFlows(StationID via); - void ReleaseFlows(StationID via); void FinalizeLocalConsumption(StationID self); private: diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 01770a6a20..f38598de10 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -63,13 +63,6 @@ #include "safeguards.h" -/** - * Static instance of FlowStat::SharesMap. - * Note: This instance is created on task start. - * Lazy creation on first usage results in a data race between the CDist threads. - */ -/* static */ const FlowStat::SharesMap FlowStat::empty_sharesmap; - /** * Check whether the given tile is a hangar. * @param t the tile to of whether it is a hangar. @@ -4629,6 +4622,25 @@ static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, in return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); } +FlowStat::iterator FlowStat::erase_item(FlowStat::iterator iter, uint flow_reduction) +{ + assert(!this->empty()); + const uint offset = iter - this->begin(); + const iterator last = this->end() - 1; + for (; iter < last; ++iter) { + *iter = { (iter + 1)->first - flow_reduction, (iter + 1)->second }; + } + --this->count; + if (this->count == 2) { + // transition from external to internal storage + ShareEntry *ptr = this->storage.ptr_shares.buffer; + this->storage.inline_shares[0] = ptr[0]; + this->storage.inline_shares[1] = ptr[1]; + free(ptr); + } + return this->begin() + offset; +} + /** * Get flow for a station. * @param st Station to get flow for. @@ -4637,7 +4649,7 @@ static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, in uint FlowStat::GetShare(StationID st) const { uint32 prev = 0; - for (SharesMap::const_iterator it = this->shares.begin(); it != this->shares.end(); ++it) { + for (const_iterator it = this->begin(); it != this->end(); ++it) { if (it->second == st) { return it->first - prev; } else { @@ -4656,30 +4668,30 @@ uint FlowStat::GetShare(StationID st) const StationID FlowStat::GetVia(StationID excluded, StationID excluded2) const { if (this->unrestricted == 0) return INVALID_STATION; - assert(!this->shares.empty()); - SharesMap::const_iterator it = this->shares.upper_bound(RandomRange(this->unrestricted)); - assert(it != this->shares.end() && it->first <= this->unrestricted); + assert(!this->empty()); + const_iterator it = std::upper_bound(this->data(), this->data() + this->count, RandomRange(this->unrestricted)); + assert(it != this->end() && it->first <= this->unrestricted); if (it->second != excluded && it->second != excluded2) return it->second; /* We've hit one of the excluded stations. * Draw another share, from outside its range. */ uint end = it->first; - uint begin = (it == this->shares.begin() ? 0 : (--it)->first); + uint begin = (it == this->begin() ? 0 : (--it)->first); uint interval = end - begin; if (interval >= this->unrestricted) return INVALID_STATION; // Only one station in the map. uint new_max = this->unrestricted - interval; uint rand = RandomRange(new_max); - SharesMap::const_iterator it2 = (rand < begin) ? this->shares.upper_bound(rand) : - this->shares.upper_bound(rand + interval); - assert(it2 != this->shares.end() && it2->first <= this->unrestricted); + const_iterator it2 = (rand < begin) ? this->upper_bound(rand) : + this->upper_bound(rand + interval); + assert(it2 != this->end() && it2->first <= this->unrestricted); if (it2->second != excluded && it2->second != excluded2) return it2->second; /* We've hit the second excluded station. * Same as before, only a bit more complicated. */ uint end2 = it2->first; - uint begin2 = (it2 == this->shares.begin() ? 0 : (--it2)->first); + uint begin2 = (it2 == this->begin() ? 0 : (--it2)->first); uint interval2 = end2 - begin2; if (interval2 >= new_max) return INVALID_STATION; // Only the two excluded stations in the map. new_max -= interval2; @@ -4689,15 +4701,15 @@ StationID FlowStat::GetVia(StationID excluded, StationID excluded2) const Swap(interval, interval2); } rand = RandomRange(new_max); - SharesMap::const_iterator it3 = this->shares.upper_bound(this->unrestricted); + const_iterator it3 = this->upper_bound(this->unrestricted); if (rand < begin) { - it3 = this->shares.upper_bound(rand); + it3 = this->upper_bound(rand); } else if (rand < begin2 - interval) { - it3 = this->shares.upper_bound(rand + interval); + it3 = this->upper_bound(rand + interval); } else { - it3 = this->shares.upper_bound(rand + interval + interval2); + it3 = this->upper_bound(rand + interval + interval2); } - assert(it3 != this->shares.end() && it3->first <= this->unrestricted); + assert(it3 != this->end() && it3->first <= this->unrestricted); return it3->second; } @@ -4708,15 +4720,13 @@ StationID FlowStat::GetVia(StationID excluded, StationID excluded2) const */ void FlowStat::Invalidate() { - assert(!this->shares.empty()); - SharesMap new_shares; + assert(!this->empty()); uint i = 0; - for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) { - new_shares[++i] = it->second; - if (it->first == this->unrestricted) this->unrestricted = i; + for (iterator it(this->begin()); it != this->end(); ++it) { + if (it->first == this->unrestricted) this->unrestricted = i + 1; + it->first = ++i; } - this->shares.swap(new_shares); - assert(!this->shares.empty() && this->unrestricted <= (--this->shares.end())->first); + assert(!this->empty() && this->unrestricted <= (this->end() - 1)->first); } /** @@ -4729,45 +4739,38 @@ void FlowStat::ChangeShare(StationID st, int flow) { /* We assert only before changing as afterwards the shares can actually * be empty. In that case the whole flow stat must be deleted then. */ - assert(!this->shares.empty()); + assert(!this->empty()); - uint removed_shares = 0; - uint added_shares = 0; uint last_share = 0; - SharesMap new_shares; - for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) { + for (iterator it(this->begin()); it != this->end(); ++it) { if (it->second == st) { - if (flow < 0) { - uint share = it->first - last_share; - if (flow == INT_MIN || (uint)(-flow) >= share) { - removed_shares += share; - if (it->first <= this->unrestricted) this->unrestricted -= share; - if (flow != INT_MIN) flow += share; - last_share = it->first; - continue; // remove the whole share - } - removed_shares += (uint)(-flow); - } else { - added_shares += (uint)(flow); + uint share = it->first - last_share; + if (flow < 0 && (flow == INT_MIN || (uint)(-flow) >= share)) { + if (it->first <= this->unrestricted) this->unrestricted -= share; + this->erase_item(it, share); + break; // remove the whole share } if (it->first <= this->unrestricted) this->unrestricted += flow; - - /* If we don't continue above the whole flow has been added or - * removed. */ + for (; it != this->end(); ++it) { + it->first += flow; + } flow = 0; + break; } - new_shares[it->first + added_shares - removed_shares] = it->second; last_share = it->first; } if (flow > 0) { - new_shares[last_share + (uint)flow] = st; + // must be non-empty here + last_share = (this->end() - 1)->first; + this->AppendShare(st, (uint)flow, true); // true to avoid changing this->unrestricted, which we fixup below if (this->unrestricted < last_share) { + // Move to front to unrestrict this->ReleaseShare(st); } else { + // First restricted item, so bump unrestricted count this->unrestricted += flow; } } - this->shares.swap(new_shares); } /** @@ -4777,28 +4780,25 @@ void FlowStat::ChangeShare(StationID st, int flow) */ void FlowStat::RestrictShare(StationID st) { - assert(!this->shares.empty()); - uint flow = 0; + assert(!this->empty()); + iterator it = this->begin(); + const iterator end = this->end(); uint last_share = 0; - SharesMap new_shares; - for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) { - if (flow == 0) { - if (it->first > this->unrestricted) return; // Not present or already restricted. - if (it->second == st) { - flow = it->first - last_share; - this->unrestricted -= flow; - } else { - new_shares[it->first] = it->second; + for (; it != end; ++it) { + if (it->first > this->unrestricted) return; // Not present or already restricted. + if (it->second == st) { + uint flow = it->first - last_share; + this->unrestricted -= flow; + if (this->unrestricted == last_share) return; // No further action required + const iterator last = end - 1; + for (iterator jt = it; jt != last; ++jt) { + *jt = { (jt + 1)->first - flow, (jt + 1)->second }; } - } else { - new_shares[it->first - flow] = it->second; + *last = { flow + (last - 1)->first, st }; + return; } last_share = it->first; } - if (flow == 0) return; - new_shares[last_share + flow] = st; - this->shares.swap(new_shares); - assert(!this->shares.empty()); } /** @@ -4808,34 +4808,27 @@ void FlowStat::RestrictShare(StationID st) */ void FlowStat::ReleaseShare(StationID st) { - assert(!this->shares.empty()); - uint flow = 0; - uint next_share = 0; - bool found = false; - for (SharesMap::reverse_iterator it(this->shares.rbegin()); it != this->shares.rend(); ++it) { - if (it->first < this->unrestricted) return; // Note: not <= as the share may hit the limit. - if (found) { - flow = next_share - it->first; - this->unrestricted += flow; - break; - } else { - if (it->first == this->unrestricted) return; // !found -> Limit not hit. - if (it->second == st) found = true; - } - next_share = it->first; - } - if (flow == 0) return; - SharesMap new_shares; - new_shares[flow] = st; - for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) { - if (it->second != st) { - new_shares[flow + it->first] = it->second; - } else { - flow = 0; + assert(!this->empty()); + iterator it = this->end() - 1; + const iterator start = this->begin(); + for (; it >= start; --it) { + if (it->first < this->unrestricted) return; // Already unrestricted + if (it->second == st) { + if (it - 1 >= start) { + uint flow = it->first - (it - 1)->first; + this->unrestricted += flow; + if (it->first == this->unrestricted) return; // No further action required + for (iterator jt = it; jt != start; --jt) { + *jt = { (jt - 1)->first + flow, (jt - 1)->second }; + } + *start = { flow, st }; + } else { + // already at start + this->unrestricted = it->first; + } + return; } } - this->shares.swap(new_shares); - assert(!this->shares.empty()); } /** @@ -4846,14 +4839,12 @@ void FlowStat::ReleaseShare(StationID st) void FlowStat::ScaleToMonthly(uint runtime) { assert(runtime > 0); - SharesMap new_shares; uint share = 0; - for (SharesMap::iterator i = this->shares.begin(); i != this->shares.end(); ++i) { + for (iterator i = this->begin(); i != this->end(); ++i) { share = max(share + 1, i->first * 30 / runtime); - new_shares[share] = i->second; if (this->unrestricted == i->first) this->unrestricted = share; + i->first = share; } - this->shares.swap(new_shares); } /** @@ -4869,7 +4860,7 @@ void FlowStatMap::AddFlow(StationID origin, StationID via, uint flow) this->insert(FlowStat(origin, via, flow)); } else { origin_it->ChangeShare(via, flow); - assert(!origin_it->GetShares()->empty()); + assert(!origin_it->empty()); } } @@ -4891,7 +4882,7 @@ void FlowStatMap::PassOnFlow(StationID origin, StationID via, uint flow) } else { prev_it->ChangeShare(via, flow); prev_it->ChangeShare(INVALID_STATION, flow); - assert(!prev_it->GetShares()->empty()); + assert(!prev_it->empty()); } } @@ -4914,7 +4905,7 @@ void FlowStatMap::FinalizeLocalConsumption(StationID self) /* If the local share is used up there must be a share for some * remote station. */ - assert(!fs.GetShares()->empty()); + assert(!fs.empty()); } } @@ -4930,7 +4921,7 @@ StationIDStack FlowStatMap::DeleteFlows(StationID via) for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) { FlowStat &s_flows = *f_it; s_flows.ChangeShare(via, INT_MIN); - if (s_flows.GetShares()->empty()) { + if (s_flows.empty()) { ret.Push(f_it->GetOrigin()); f_it = this->erase(f_it); } else { @@ -4951,17 +4942,6 @@ void FlowStatMap::RestrictFlows(StationID via) } } -/** - * Release all flows at a station for specific cargo and destination. - * @param via Remote station of flows to be released. - */ -void FlowStatMap::ReleaseFlows(StationID via) -{ - for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) { - it->ReleaseShare(via); - } -} - /** * Get the sum of all flows from this FlowStatMap. * @return sum of all flows. @@ -4970,7 +4950,7 @@ uint FlowStatMap::GetFlow() const { uint ret = 0; for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) { - ret += (--(i->GetShares()->end()))->first; + ret += (i->end() - 1)->first; } return ret; } @@ -4998,7 +4978,7 @@ uint FlowStatMap::GetFlowFrom(StationID from) const { FlowStatMap::const_iterator i = this->find(from); if (i == this->end()) return 0; - return (--(i->GetShares()->end()))->first; + return (i->end() - 1)->first; } /** diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 50f3cd75cd..4589704ff9 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -1515,9 +1515,8 @@ struct StationViewWindow : public Window { for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) { StationID from = it->GetOrigin(); CargoDataEntry *source_entry = cargo_entry->InsertOrRetrieve(from); - const FlowStat::SharesMap *shares = it->GetShares(); uint32 prev_count = 0; - for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) { + for (FlowStat::const_iterator flow_it = it->begin(); flow_it != it->end(); ++flow_it) { StationID via = flow_it->second; CargoDataEntry *via_entry = source_entry->InsertOrRetrieve(via); if (via == this->window_number) { @@ -1546,9 +1545,8 @@ struct StationViewWindow : public Window { const FlowStatMap &flowmap = Station::Get(next)->goods[cargo].flows; FlowStatMap::const_iterator map_it = flowmap.find(source); if (map_it != flowmap.end()) { - const FlowStat::SharesMap *shares = map_it->GetShares(); uint32 prev_count = 0; - for (FlowStat::SharesMap::const_iterator i = shares->begin(); i != shares->end(); ++i) { + for (FlowStat::const_iterator i = map_it->begin(); i != map_it->end(); ++i) { tmp.InsertOrRetrieve(i->second)->Update(i->first - prev_count); prev_count = i->first; } @@ -1598,8 +1596,7 @@ struct StationViewWindow : public Window { for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) { StationID from = it->GetOrigin(); const CargoDataEntry *source_entry = source_dest->Retrieve(from); - const FlowStat::SharesMap *shares = it->GetShares(); - for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) { + for (FlowStat::const_iterator flow_it = it->begin(); flow_it != it->end(); ++flow_it) { const CargoDataEntry *via_entry = source_entry->Retrieve(flow_it->second); for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) { CargoDataEntry *dest_entry = *dest_it;