OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

linkgraphschedule.cpp
Go to the documentation of this file.
1 /* $Id: linkgraphschedule.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
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
24 void LinkGraphSchedule::SpawnNext()
25 {
26 if (this->schedule.empty()) return;
27 LinkGraph *next = this->schedule.front();
28 LinkGraph *first = next;
29 while (next->Size() < 2) {
30 this->schedule.splice(this->schedule.end(), this->schedule, this->schedule.begin());
31 next = this->schedule.front();
32 if (next == first) return;
33 }
34 assert(next == LinkGraph::Get(next->index));
35 this->schedule.pop_front();
36 if (LinkGraphJob::CanAllocateItem()) {
37 LinkGraphJob *job = new LinkGraphJob(*next);
38 job->SpawnThread();
39 this->running.push_back(job);
40 } else {
41 NOT_REACHED();
42 }
43 }
44
48 void LinkGraphSchedule::JoinNext()
49 {
50 if (this->running.empty()) return;
51 LinkGraphJob *next = this->running.front();
52 if (!next->IsFinished()) return;
53 this->running.pop_front();
54 LinkGraphID id = next->LinkGraphIndex();
55 delete next; // implicitly joins the thread
56 if (LinkGraph::IsValidID(id)) {
57 LinkGraph *lg = LinkGraph::Get(id);
58 this->Unqueue(lg); // Unqueue to avoid double-queueing recycled IDs.
59 this->Queue(lg);
60 }
61 }
62
68 /* static */ void LinkGraphSchedule::Run(void *j)
69 {
70 LinkGraphJob *job = (LinkGraphJob *)j;
71 LinkGraphSchedule *schedule = LinkGraphSchedule::Instance();
72 for (uint i = 0; i < lengthof(schedule->handlers); ++i) {
73 schedule->handlers[i]->Run(*job);
74 }
75 }
76
81 void LinkGraphSchedule::SpawnAll()
82 {
83 for (JobList::iterator i = this->running.begin(); i != this->running.end(); ++i) {
84 (*i)->SpawnThread();
85 }
86 }
87
91 /* static */ void LinkGraphSchedule::Clear()
92 {
93 LinkGraphSchedule *inst = LinkGraphSchedule::Instance();
94 for (JobList::iterator i(inst->running.begin()); i != inst->running.end(); ++i) {
95 (*i)->JoinThread();
96 }
97 inst->running.clear();
98 inst->schedule.clear();
99 }
100
106 void LinkGraphSchedule::ShiftDates(int interval)
107 {
108 LinkGraph *lg;
109 FOR_ALL_LINK_GRAPHS(lg) lg->ShiftDates(interval);
110 LinkGraphJob *lgj;
111 FOR_ALL_LINK_GRAPH_JOBS(lgj) lgj->ShiftJoinDate(interval);
112 }
113
117 LinkGraphSchedule::LinkGraphSchedule()
118 {
119 this->handlers[0] = new InitHandler;
120 this->handlers[1] = new DemandHandler;
121 this->handlers[2] = new MCFHandler<MCF1stPass>;
122 this->handlers[3] = new FlowMapper(false);
123 this->handlers[4] = new MCFHandler<MCF2ndPass>;
124 this->handlers[5] = new FlowMapper(true);
125 }
126
130 LinkGraphSchedule::~LinkGraphSchedule()
131 {
132 this->Clear();
133 for (uint i = 0; i < lengthof(this->handlers); ++i) {
134 delete this->handlers[i];
135 }
136 }
137
141 /* static */ LinkGraphSchedule *LinkGraphSchedule::Instance()
142 {
143 static LinkGraphSchedule inst;
144 return &inst;
145 }
146
151 void OnTick_LinkGraph()
152 {
153 if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
154 Date offset = _date % _settings_game.linkgraph.recalc_interval;
155 if (offset == 0) {
156 LinkGraphSchedule::Instance()->SpawnNext();
157 } else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
158 LinkGraphSchedule::Instance()->JoinNext();
159 }
160 }
161
162