Index: src/station.cpp =================================================================== --- src/station.cpp (revision 27177) +++ src/station.cpp (working copy) @@ -107,7 +107,7 @@ } lg->RemoveNode(this->goods[c].node); if (lg->Size() == 0) { - LinkGraphSchedule::Instance()->Unqueue(lg); + LinkGraphSchedule::instance.Unqueue(lg); delete lg; } } Index: src/station_base.h =================================================================== --- src/station_base.h (revision 27177) +++ src/station_base.h (working copy) @@ -37,6 +37,8 @@ public: typedef std::map SharesMap; + static const SharesMap empty_sharesmap; + /** * Invalid constructor. This can't be called as a FlowStat must not be * empty. However, the constructor must be defined and reachable for Index: src/toolbar_gui.cpp =================================================================== --- src/toolbar_gui.cpp (revision 27177) +++ src/toolbar_gui.cpp (working copy) @@ -1119,7 +1119,7 @@ _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR); Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); /* If you open a savegame as scenario there may already be link graphs.*/ - LinkGraphSchedule::Instance()->ShiftDates(new_date - _date); + LinkGraphSchedule::instance.ShiftDates(new_date - _date); SetDate(new_date, 0); } Index: src/saveload/linkgraph_sl.cpp =================================================================== --- src/saveload/linkgraph_sl.cpp (revision 27177) +++ src/saveload/linkgraph_sl.cpp (working copy) @@ -209,7 +209,7 @@ */ static void Load_LGRS() { - SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc()); + SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); } /** @@ -218,7 +218,7 @@ */ void AfterLoadLinkGraphs() { - LinkGraphSchedule::Instance()->SpawnAll(); + LinkGraphSchedule::instance.SpawnAll(); } /** @@ -250,7 +250,7 @@ */ static void Save_LGRS() { - SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc()); + SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); } /** @@ -258,7 +258,7 @@ */ static void Ptrs_LGRS() { - SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc()); + SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); } extern const ChunkHandler _linkgraph_chunk_handlers[] = { Index: src/cheat_gui.cpp =================================================================== --- src/cheat_gui.cpp (revision 27177) +++ src/cheat_gui.cpp (working copy) @@ -102,7 +102,7 @@ if (p1 == _cur_year) return _cur_year; Date new_date = ConvertYMDToDate(p1, ymd.month, ymd.day); - LinkGraphSchedule::Instance()->ShiftDates(new_date - _date); + LinkGraphSchedule::instance.ShiftDates(new_date - _date); SetDate(new_date, _date_fract); EnginesMonthlyLoop(); SetWindowDirty(WC_STATUS_BAR, 0); Index: src/linkgraph/linkgraphschedule.h =================================================================== --- src/linkgraph/linkgraphschedule.h (revision 27177) +++ src/linkgraph/linkgraphschedule.h (working copy) @@ -51,8 +51,8 @@ public: /* This is a tick where not much else is happening, so a small lag might go unnoticed. */ static const uint SPAWN_JOIN_TICK = 21; ///< Tick when jobs are spawned or joined every day. + static LinkGraphSchedule instance; - static LinkGraphSchedule *Instance(); static void Run(void *j); static void Clear(); Index: src/linkgraph/mcf.cpp =================================================================== --- src/linkgraph/mcf.cpp (revision 27177) +++ src/linkgraph/mcf.cpp (working copy) @@ -146,15 +146,14 @@ */ void SetNode(NodeID source, NodeID node) { - static const FlowStat::SharesMap empty; const FlowStatMap &flows = this->job[node].Flows(); FlowStatMap::const_iterator it = flows.find(this->job[source].Station()); if (it != flows.end()) { this->it = it->second.GetShares()->begin(); this->end = it->second.GetShares()->end(); } else { - this->it = empty.begin(); - this->end = empty.end(); + this->it = FlowStat::empty_sharesmap.begin(); + this->end = FlowStat::empty_sharesmap.end(); } } @@ -378,11 +377,10 @@ */ bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id) { - static Path *invalid_path = new Path(INVALID_NODE, true); Path *at_next_pos = path[next_id]; /* this node has already been searched */ - if (at_next_pos == invalid_path) return false; + if (at_next_pos == Path::invalid_path) return false; if (at_next_pos == NULL) { /* Summarize paths; add up the paths with the same source and next hop @@ -430,7 +428,7 @@ * could be found in this branch, thus it has to be searched again next * time we spot it. */ - path[next_id] = found ? NULL : invalid_path; + path[next_id] = found ? NULL : Path::invalid_path; return found; } Index: src/linkgraph/linkgraphjob.cpp =================================================================== --- src/linkgraph/linkgraphjob.cpp (revision 27177) +++ src/linkgraph/linkgraphjob.cpp (working copy) @@ -20,6 +20,13 @@ INSTANTIATE_POOL_METHODS(LinkGraphJob) /** + * Static instance of an invalid path. + * Note: This instance is created on task start. + * Lazy creation on first usage results in a data race between the CDist threads. + */ +/* static */ Path *Path::invalid_path = new Path(INVALID_NODE, true); + +/** * Create a link graph job from a link graph. The link graph will be copied so * that the calculations don't interfer with the normal operations on the * original. The job is immediately started. Index: src/linkgraph/linkgraphjob.h =================================================================== --- src/linkgraph/linkgraphjob.h (revision 27177) +++ src/linkgraph/linkgraphjob.h (working copy) @@ -343,6 +343,8 @@ */ class Path { public: + static Path *invalid_path; + Path(NodeID n, bool source = false); /** Get the node this leg passes. */ Index: src/linkgraph/linkgraphschedule.cpp =================================================================== --- src/linkgraph/linkgraphschedule.cpp (revision 27177) +++ src/linkgraph/linkgraphschedule.cpp (working copy) @@ -17,6 +17,13 @@ #include "flowmapper.h" /** + * Static instance of LinkGraphSchedule. + * Note: This instance is created on task start. + * Lazy creation on first usage results in a data race between the CDist threads. + */ +/* static */ LinkGraphSchedule LinkGraphSchedule::instance; + +/** * Start the next job in the schedule. */ void LinkGraphSchedule::SpawnNext() @@ -66,9 +73,8 @@ /* static */ void LinkGraphSchedule::Run(void *j) { LinkGraphJob *job = (LinkGraphJob *)j; - LinkGraphSchedule *schedule = LinkGraphSchedule::Instance(); - for (uint i = 0; i < lengthof(schedule->handlers); ++i) { - schedule->handlers[i]->Run(*job); + for (uint i = 0; i < lengthof(instance.handlers); ++i) { + instance.handlers[i]->Run(*job); } } @@ -88,12 +94,11 @@ */ /* static */ void LinkGraphSchedule::Clear() { - LinkGraphSchedule *inst = LinkGraphSchedule::Instance(); - for (JobList::iterator i(inst->running.begin()); i != inst->running.end(); ++i) { + for (JobList::iterator i(instance.running.begin()); i != instance.running.end(); ++i) { (*i)->JoinThread(); } - inst->running.clear(); - inst->schedule.clear(); + instance.running.clear(); + instance.schedule.clear(); } /** @@ -134,15 +139,6 @@ } /** - * Retrieve the link graph schedule or create it if necessary. - */ -/* static */ LinkGraphSchedule *LinkGraphSchedule::Instance() -{ - static LinkGraphSchedule inst; - return &inst; -} - -/** * Spawn or join a link graph job or compress a link graph if any link graph is * due to do so. */ @@ -151,9 +147,9 @@ if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return; Date offset = _date % _settings_game.linkgraph.recalc_interval; if (offset == 0) { - LinkGraphSchedule::Instance()->SpawnNext(); + LinkGraphSchedule::instance.SpawnNext(); } else if (offset == _settings_game.linkgraph.recalc_interval / 2) { - LinkGraphSchedule::Instance()->JoinNext(); + LinkGraphSchedule::instance.JoinNext(); } } Index: src/station_cmd.cpp =================================================================== --- src/station_cmd.cpp (revision 27177) +++ src/station_cmd.cpp (working copy) @@ -57,6 +57,13 @@ #include "table/strings.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. * @pre IsTileType(t, MP_STATION) @@ -3515,7 +3522,7 @@ if (ge2.link_graph == INVALID_LINK_GRAPH) { if (LinkGraph::CanAllocateItem()) { lg = new LinkGraph(cargo); - LinkGraphSchedule::Instance()->Queue(lg); + LinkGraphSchedule::instance.Queue(lg); ge2.link_graph = lg->index; ge2.node = lg->AddNode(st2); } else { @@ -3537,11 +3544,11 @@ if (ge1.link_graph != ge2.link_graph) { LinkGraph *lg2 = LinkGraph::Get(ge2.link_graph); if (lg->Size() < lg2->Size()) { - LinkGraphSchedule::Instance()->Unqueue(lg); + LinkGraphSchedule::instance.Unqueue(lg); lg2->Merge(lg); // Updates GoodsEntries of lg lg = lg2; } else { - LinkGraphSchedule::Instance()->Unqueue(lg2); + LinkGraphSchedule::instance.Unqueue(lg2); lg->Merge(lg2); // Updates GoodsEntries of lg2 } } @@ -3663,7 +3670,7 @@ if (ge.link_graph == INVALID_LINK_GRAPH) { if (LinkGraph::CanAllocateItem()) { lg = new LinkGraph(type); - LinkGraphSchedule::Instance()->Queue(lg); + LinkGraphSchedule::instance.Queue(lg); ge.link_graph = lg->index; ge.node = lg->AddNode(st); } else {