(svn r27729) -Codechange: Do not count static NewGRF when checking for the maximum...
[openttd.git] / src / linkgraph / linkgraphschedule.cpp
bloba65783a5e78316f32b28918eb13703d958cf7a83
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file linkgraphschedule.cpp Definition of link graph schedule used for cargo distribution. */
12 #include "../stdafx.h"
13 #include "linkgraphschedule.h"
14 #include "init.h"
15 #include "demands.h"
16 #include "mcf.h"
17 #include "flowmapper.h"
19 #include "../safeguards.h"
21 /**
22 * Static instance of LinkGraphSchedule.
23 * Note: This instance is created on task start.
24 * Lazy creation on first usage results in a data race between the CDist threads.
26 /* static */ LinkGraphSchedule LinkGraphSchedule::instance;
28 /**
29 * Start the next job in the schedule.
31 void LinkGraphSchedule::SpawnNext()
33 if (this->schedule.empty()) return;
34 LinkGraph *next = this->schedule.front();
35 LinkGraph *first = next;
36 while (next->Size() < 2) {
37 this->schedule.splice(this->schedule.end(), this->schedule, this->schedule.begin());
38 next = this->schedule.front();
39 if (next == first) return;
41 assert(next == LinkGraph::Get(next->index));
42 this->schedule.pop_front();
43 if (LinkGraphJob::CanAllocateItem()) {
44 LinkGraphJob *job = new LinkGraphJob(*next);
45 job->SpawnThread();
46 this->running.push_back(job);
47 } else {
48 NOT_REACHED();
52 /**
53 * Join the next finished job, if available.
55 void LinkGraphSchedule::JoinNext()
57 if (this->running.empty()) return;
58 LinkGraphJob *next = this->running.front();
59 if (!next->IsFinished()) return;
60 this->running.pop_front();
61 LinkGraphID id = next->LinkGraphIndex();
62 delete next; // implicitly joins the thread
63 if (LinkGraph::IsValidID(id)) {
64 LinkGraph *lg = LinkGraph::Get(id);
65 this->Unqueue(lg); // Unqueue to avoid double-queueing recycled IDs.
66 this->Queue(lg);
70 /**
71 * Run all handlers for the given Job. This method is tailored to
72 * ThreadObject::New.
73 * @param j Pointer to a link graph job.
75 /* static */ void LinkGraphSchedule::Run(void *j)
77 LinkGraphJob *job = (LinkGraphJob *)j;
78 for (uint i = 0; i < lengthof(instance.handlers); ++i) {
79 instance.handlers[i]->Run(*job);
83 /**
84 * Start all threads in the running list. This is only useful for save/load.
85 * Usually threads are started when the job is created.
87 void LinkGraphSchedule::SpawnAll()
89 for (JobList::iterator i = this->running.begin(); i != this->running.end(); ++i) {
90 (*i)->SpawnThread();
94 /**
95 * Clear all link graphs and jobs from the schedule.
97 /* static */ void LinkGraphSchedule::Clear()
99 for (JobList::iterator i(instance.running.begin()); i != instance.running.end(); ++i) {
100 (*i)->JoinThread();
102 instance.running.clear();
103 instance.schedule.clear();
107 * Shift all dates (join dates and edge annotations) of link graphs and link
108 * graph jobs by the number of days given.
109 * @param interval Number of days to be added or subtracted.
111 void LinkGraphSchedule::ShiftDates(int interval)
113 LinkGraph *lg;
114 FOR_ALL_LINK_GRAPHS(lg) lg->ShiftDates(interval);
115 LinkGraphJob *lgj;
116 FOR_ALL_LINK_GRAPH_JOBS(lgj) lgj->ShiftJoinDate(interval);
120 * Create a link graph schedule and initialize its handlers.
122 LinkGraphSchedule::LinkGraphSchedule()
124 this->handlers[0] = new InitHandler;
125 this->handlers[1] = new DemandHandler;
126 this->handlers[2] = new MCFHandler<MCF1stPass>;
127 this->handlers[3] = new FlowMapper(false);
128 this->handlers[4] = new MCFHandler<MCF2ndPass>;
129 this->handlers[5] = new FlowMapper(true);
133 * Delete a link graph schedule and its handlers.
135 LinkGraphSchedule::~LinkGraphSchedule()
137 this->Clear();
138 for (uint i = 0; i < lengthof(this->handlers); ++i) {
139 delete this->handlers[i];
144 * Spawn or join a link graph job or compress a link graph if any link graph is
145 * due to do so.
147 void OnTick_LinkGraph()
149 if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
150 Date offset = _date % _settings_game.linkgraph.recalc_interval;
151 if (offset == 0) {
152 LinkGraphSchedule::instance.SpawnNext();
153 } else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
154 LinkGraphSchedule::instance.JoinNext();