# linkgraphschedule.cpp

Go to the documentation of this file.

    00001 /* $Id: linkgraphschedule.cpp 26347 2014-02-16 18:42:59Z fonsinchen $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "../stdafx.h"
    00013 #include "linkgraphschedule.h"
    00014 #include "init.h"
    00015 #include "demands.h"
    00016 #include "mcf.h"
    00017 #include "flowmapper.h"
    00018
    00022 void LinkGraphSchedule::SpawnNext()
    00023 {
    00024   if (this->schedule.empty()) return;
    00025   LinkGraph *next = this->schedule.front();
    00026   LinkGraph *first = next;
    00027   while (next->Size() < 2) {
    00028     this->schedule.splice(this->schedule.end(), this->schedule, this->schedule.begin());
    00029     next = this->schedule.front();
    00030     if (next == first) return;
    00031   }
    00032   assert(next == LinkGraph::Get(next->index));
    00033   this->schedule.pop_front();
    00034   if (LinkGraphJob::CanAllocateItem()) {
    00035     LinkGraphJob *job = new LinkGraphJob(*next);
    00036     job->SpawnThread();
    00037     this->running.push_back(job);
    00038   } else {
    00039     NOT_REACHED();
    00040   }
    00041 }
    00042
    00046 void LinkGraphSchedule::JoinNext()
    00047 {
    00048   if (this->running.empty()) return;
    00049   LinkGraphJob *next = this->running.front();
    00050   if (!next->IsFinished()) return;
    00051   this->running.pop_front();
    00052   LinkGraphID id = next->LinkGraphIndex();
    00053   delete next; // implicitly joins the thread
    00054   if (LinkGraph::IsValidID(id)) {
    00055     LinkGraph *lg = LinkGraph::Get(id);
    00056     this->Unqueue(lg); // Unqueue to avoid double-queueing recycled IDs.
    00057     this->Queue(lg);
    00058   }
    00059 }
    00060
    00066 /* static */ void LinkGraphSchedule::Run(void *j)
    00067 {
    00068   LinkGraphJob *job = (LinkGraphJob *)j;
    00069   LinkGraphSchedule *schedule = LinkGraphSchedule::Instance();
    00070   for (uint i = 0; i < lengthof(schedule->handlers); ++i) {
    00071     schedule->handlers[i]->Run(*job);
    00072   }
    00073 }
    00074
    00079 void LinkGraphSchedule::SpawnAll()
    00080 {
    00081   for (JobList::iterator i = this->running.begin(); i != this->running.end(); ++i) {
    00082     (*i)->SpawnThread();
    00083   }
    00084 }
    00085
    00089 /* static */ void LinkGraphSchedule::Clear()
    00090 {
    00091   LinkGraphSchedule *inst = LinkGraphSchedule::Instance();
    00092   for (JobList::iterator i(inst->running.begin()); i != inst->running.end(); ++i) {
    00093     (*i)->JoinThread();
    00094   }
    00095   inst->running.clear();
    00096   inst->schedule.clear();
    00097 }
    00098
    00104 void LinkGraphSchedule::ShiftDates(int interval)
    00105 {
    00106   LinkGraph *lg;
    00107   FOR_ALL_LINK_GRAPHS(lg) lg->ShiftDates(interval);
    00108   LinkGraphJob *lgj;
    00109   FOR_ALL_LINK_GRAPH_JOBS(lgj) lgj->ShiftJoinDate(interval);
    00110 }
    00111
    00115 LinkGraphSchedule::LinkGraphSchedule()
    00116 {
    00117   this->handlers[0] = new InitHandler;
    00118   this->handlers[1] = new DemandHandler;
    00119   this->handlers[2] = new MCFHandler<MCF1stPass>;
    00120   this->handlers[3] = new FlowMapper(false);
    00121   this->handlers[4] = new MCFHandler<MCF2ndPass>;
    00122   this->handlers[5] = new FlowMapper(true);
    00123 }
    00124
    00128 LinkGraphSchedule::~LinkGraphSchedule()
    00129 {
    00130   this->Clear();
    00131   for (uint i = 0; i < lengthof(this->handlers); ++i) {
    00132     delete this->handlers[i];
    00133   }
    00134 }
    00135
    00139 /* static */ LinkGraphSchedule *LinkGraphSchedule::Instance()
    00140 {
    00141   static LinkGraphSchedule inst;
    00142   return &inst;
    00143 }
    00144
    00149 void OnTick_LinkGraph()
    00150 {
    00151   if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
    00152   Date offset = _date % _settings_game.linkgraph.recalc_interval;
    00153   if (offset == 0) {
    00154     LinkGraphSchedule::Instance()->SpawnNext();
    00155   } else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
    00156     LinkGraphSchedule::Instance()->JoinNext();
    00157   }
    00158 }
    00159
    00160