OpenTTD
linkgraphschedule.cpp
Go to the documentation of this file.
1 /* $Id: linkgraphschedule.cpp 27178 2015-03-07 18:27:01Z frosch $ */
2 
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  */
9 
12 #include "../stdafx.h"
13 #include "linkgraphschedule.h"
14 #include "init.h"
15 #include "demands.h"
16 #include "mcf.h"
17 #include "flowmapper.h"
18 
19 #include "../safeguards.h"
20 
27 
32 {
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;
40  }
41  assert(next == LinkGraph::Get(next->index));
42  this->schedule.pop_front();
44  LinkGraphJob *job = new LinkGraphJob(*next);
45  job->SpawnThread();
46  this->running.push_back(job);
47  } else {
48  NOT_REACHED();
49  }
50 }
51 
56 {
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);
67  }
68 }
69 
75 /* static */ void LinkGraphSchedule::Run(void *j)
76 {
77  LinkGraphJob *job = (LinkGraphJob *)j;
78  for (uint i = 0; i < lengthof(instance.handlers); ++i) {
79  instance.handlers[i]->Run(*job);
80  }
81 }
82 
88 {
89  for (JobList::iterator i = this->running.begin(); i != this->running.end(); ++i) {
90  (*i)->SpawnThread();
91  }
92 }
93 
97 /* static */ void LinkGraphSchedule::Clear()
98 {
99  for (JobList::iterator i(instance.running.begin()); i != instance.running.end(); ++i) {
100  (*i)->JoinThread();
101  }
102  instance.running.clear();
103  instance.schedule.clear();
104 }
105 
112 {
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);
117 }
118 
123 {
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);
130 }
131 
136 {
137  this->Clear();
138  for (uint i = 0; i < lengthof(this->handlers); ++i) {
139  delete this->handlers[i];
140  }
141 }
142 
148 {
151  if (offset == 0) {
152  LinkGraphSchedule::instance.SpawnNext();
153  } else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
154  LinkGraphSchedule::instance.JoinNext();
155  }
156 }
157 
158