(svn r25354) -Add: link graph schedule and typedefs for LinkGraph and related classes

This commit is contained in:
fonsinchen 2013-06-09 12:58:37 +00:00
parent 22f56ffdd7
commit c32eea02dd
13 changed files with 361 additions and 0 deletions

View File

@ -333,6 +333,7 @@
<ClCompile Include="..\src\landscape.cpp" />
<ClCompile Include="..\src\linkgraph\linkgraph.cpp" />
<ClCompile Include="..\src\linkgraph\linkgraphjob.cpp" />
<ClCompile Include="..\src\linkgraph\linkgraphschedule.cpp" />
<ClCompile Include="..\src\map.cpp" />
<ClCompile Include="..\src\misc.cpp" />
<ClCompile Include="..\src\mixer.cpp" />
@ -472,11 +473,14 @@
<ClInclude Include="..\src\landscape.h" />
<ClInclude Include="..\src\landscape_type.h" />
<ClInclude Include="..\src\language.h" />
<ClInclude Include="..\src\linkgraph\init.h" />
<ClInclude Include="..\src\linkgraph\linkgraph.h" />
<ClInclude Include="..\src\linkgraph\linkgraph_base.h" />
<ClInclude Include="..\src\linkgraph\linkgraph_gui.h" />
<ClInclude Include="..\src\linkgraph\linkgraph_type.h" />
<ClInclude Include="..\src\linkgraph\linkgraphjob.h" />
<ClInclude Include="..\src\linkgraph\linkgraphjob_base.h" />
<ClInclude Include="..\src\linkgraph\linkgraphschedule.h" />
<ClInclude Include="..\src\livery.h" />
<ClInclude Include="..\src\map_func.h" />
<ClInclude Include="..\src\map_type.h" />

View File

@ -228,6 +228,9 @@
<ClCompile Include="..\src\linkgraph\linkgraphjob.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\linkgraph\linkgraphschedule.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\map.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -645,6 +648,9 @@
<ClInclude Include="..\src\language.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\linkgraph\init.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\linkgraph\linkgraph.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -660,6 +666,12 @@
<ClInclude Include="..\src\linkgraph\linkgraphjob.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\linkgraph\linkgraphjob_base.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\linkgraph\linkgraphschedule.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\livery.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -602,6 +602,10 @@
RelativePath=".\..\src\linkgraph\linkgraphjob.cpp"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraphschedule.cpp"
>
</File>
<File
RelativePath=".\..\src\map.cpp"
>
@ -1162,6 +1166,10 @@
RelativePath=".\..\src\language.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\init.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraph.h"
>
@ -1182,6 +1190,14 @@
RelativePath=".\..\src\linkgraph\linkgraphjob.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraphjob_base.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraphschedule.h"
>
</File>
<File
RelativePath=".\..\src\livery.h"
>

View File

@ -599,6 +599,10 @@
RelativePath=".\..\src\linkgraph\linkgraphjob.cpp"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraphschedule.cpp"
>
</File>
<File
RelativePath=".\..\src\map.cpp"
>
@ -1159,6 +1163,10 @@
RelativePath=".\..\src\language.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\init.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraph.h"
>
@ -1179,6 +1187,14 @@
RelativePath=".\..\src\linkgraph\linkgraphjob.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraphjob_base.h"
>
</File>
<File
RelativePath=".\..\src\linkgraph\linkgraphschedule.h"
>
</File>
<File
RelativePath=".\..\src\livery.h"
>

View File

@ -41,6 +41,7 @@ ini_load.cpp
landscape.cpp
linkgraph/linkgraph.cpp
linkgraph/linkgraphjob.cpp
linkgraph/linkgraphschedule.cpp
map.cpp
misc.cpp
mixer.cpp
@ -205,11 +206,14 @@ ini_type.h
landscape.h
landscape_type.h
language.h
linkgraph/init.h
linkgraph/linkgraph.h
linkgraph/linkgraph_base.h
linkgraph/linkgraph_gui.h
linkgraph/linkgraph_type.h
linkgraph/linkgraphjob.h
linkgraph/linkgraphjob_base.h
linkgraph/linkgraphschedule.h
livery.h
map_func.h
map_type.h

View File

@ -1295,6 +1295,7 @@ void OnTick_Station();
void OnTick_Industry();
void OnTick_Companies();
void OnTick_LinkGraph();
void CallLandscapeTick()
{
@ -1304,4 +1305,5 @@ void CallLandscapeTick()
OnTick_Industry();
OnTick_Companies();
OnTick_LinkGraph();
}

27
src/linkgraph/init.h Normal file
View File

@ -0,0 +1,27 @@
/** @file init.h Declaration of initializing link graph handler. */
#ifndef INIT_H
#define INIT_H
#include "linkgraphjob_base.h"
/**
* Stateless, thread safe initialization hander. Initializes node and edge
* annotations.
*/
class InitHandler : public ComponentHandler {
public:
/**
* Initialize the link graph job.
* @param job Job to be initialized.
*/
virtual void Run(LinkGraphJob &job) const { job.Init(); }
/**
* Virtual destructor has to be defined because of virtual Run().
*/
virtual ~InitHandler() {}
};
#endif /* INIT_H */

View File

@ -13,6 +13,7 @@
#define LINKGRAPH_BASE_H
#include "linkgraph.h"
#include "linkgraphschedule.h"
typedef LinkGraph::Node Node;
typedef LinkGraph::Edge Edge;

View File

@ -0,0 +1,23 @@
/* $Id$ */
/*
* This file is part of OpenTTD.
* 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.
* 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.
* 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/>.
*/
/** @file linkgraphjob_base.h Some typedefs for component handlers. */
#ifndef LINKGRAPHJOB_BASE_H
#define LINKGRAPHJOB_BASE_H
#include "linkgraph.h"
#include "linkgraphjob.h"
#include "linkgraphschedule.h"
typedef LinkGraphJob::Node Node;
typedef LinkGraphJob::Edge Edge;
typedef LinkGraphJob::EdgeIterator EdgeIterator;
#endif /* LINKGRAPHJOB_BASE_H */

View File

@ -0,0 +1,168 @@
/* $Id$ */
/*
* This file is part of OpenTTD.
* 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.
* 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.
* 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/>.
*/
/** @file linkgraphschedule.cpp Definition of link graph schedule used for cargo distribution. */
#include "../stdafx.h"
#include "linkgraphschedule.h"
#include "init.h"
/**
* Spawn a thread if possible and run the link graph job in the thread. If
* that's not possible run the job right now in the current thread.
* @param job Job to be executed.
*/
void LinkGraphSchedule::SpawnThread(LinkGraphJob *job)
{
if (!ThreadObject::New(&(LinkGraphSchedule::Run), job, &job->thread)) {
job->thread = NULL;
/* Of course this will hang a bit.
* On the other hand, if you want to play games which make this hang noticably
* on a platform without threads then you'll probably get other problems first.
* OK:
* If someone comes and tells me that this hangs for him/her, I'll implement a
* smaller grained "Step" method for all handlers and add some more ticks where
* "Step" is called. No problem in principle.
*/
LinkGraphSchedule::Run(job);
}
}
/**
* Join the calling thread with the given job's thread if threading is enabled.
* @param job Job whose execution thread is to be joined.
*/
void LinkGraphSchedule::JoinThread(LinkGraphJob *job)
{
if (job->thread != NULL) {
job->thread->Join();
delete job->thread;
job->thread = NULL;
}
}
/**
* Start the next job in the schedule.
*/
void LinkGraphSchedule::SpawnNext()
{
if (this->schedule.empty()) return;
LinkGraph *next = this->schedule.front();
assert(next == LinkGraph::Get(next->index));
this->schedule.pop_front();
if (LinkGraphJob::CanAllocateItem()) {
LinkGraphJob *job = new LinkGraphJob(*next);
this->SpawnThread(job);
this->running.push_back(job);
} else {
NOT_REACHED();
}
}
/**
* Join the next finished job, if available.
*/
void LinkGraphSchedule::JoinNext()
{
if (this->running.empty()) return;
LinkGraphJob *next = this->running.front();
if (!next->IsFinished()) return;
this->running.pop_front();
LinkGraphID id = next->LinkGraphIndex();
this->JoinThread(next);
delete next;
if (LinkGraph::IsValidID(id)) {
LinkGraph *lg = LinkGraph::Get(id);
this->Unqueue(lg); // Unqueue to avoid double-queueing recycled IDs.
this->Queue(lg);
}
}
/**
* Run all handlers for the given Job. This method is tailored to
* ThreadObject::New.
* @param j Pointer to a link graph job.
*/
/* 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);
}
}
/**
* Start all threads in the running list. This is only useful for save/load.
* Usually threads are started when the job is created.
*/
void LinkGraphSchedule::SpawnAll()
{
for (JobList::iterator i = this->running.begin(); i != this->running.end(); ++i) {
this->SpawnThread(*i);
}
}
/**
* Clear all link graphs and jobs from the schedule.
*/
/* static */ void LinkGraphSchedule::Clear()
{
LinkGraphSchedule *inst = LinkGraphSchedule::Instance();
for (JobList::iterator i(inst->running.begin()); i != inst->running.end(); ++i) {
inst->JoinThread(*i);
}
inst->running.clear();
inst->schedule.clear();
}
/**
* Create a link graph schedule and initialize its handlers.
*/
LinkGraphSchedule::LinkGraphSchedule()
{
this->handlers[0] = new InitHandler;
}
/**
* Delete a link graph schedule and its handlers.
*/
LinkGraphSchedule::~LinkGraphSchedule()
{
this->Clear();
for (uint i = 0; i < lengthof(this->handlers); ++i) {
delete this->handlers[i];
}
}
/**
* 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.
*/
void OnTick_LinkGraph()
{
if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
Date offset = _date % _settings_game.linkgraph.recalc_interval;
if (offset == 0) {
LinkGraphSchedule::Instance()->SpawnNext();
} else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
LinkGraphSchedule::Instance()->JoinNext();
}
}

View File

@ -0,0 +1,83 @@
/* $Id$ */
/*
* This file is part of OpenTTD.
* 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.
* 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.
* 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/>.
*/
/** @file linkgraphschedule.h Declaration of link graph schedule used for cargo distribution. */
#ifndef LINKGRAPHSCHEDULE_H
#define LINKGRAPHSCHEDULE_H
#include "linkgraph.h"
class LinkGraphJob;
/**
* A handler doing "something" on a link graph component. It must not keep any
* state as it is called concurrently from different threads.
*/
class ComponentHandler {
public:
/**
* Destroy the handler. Must be given due to virtual Run.
*/
virtual ~ComponentHandler() {}
/**
* Run the handler. A link graph handler must not read or write any data
* outside the given component as that would create a potential desync.
* @param job Link graph component to run the handler on.
*/
virtual void Run(LinkGraphJob &job) const = 0;
};
class LinkGraphSchedule {
private:
LinkGraphSchedule();
~LinkGraphSchedule();
typedef std::list<LinkGraph *> GraphList;
typedef std::list<LinkGraphJob *> JobList;
friend const SaveLoad *GetLinkGraphScheduleDesc();
protected:
ComponentHandler *handlers[1]; ///< Handlers to be run for each job.
GraphList schedule; ///< Queue for new jobs.
JobList running; ///< Currently running jobs.
void SpawnThread(LinkGraphJob *job);
void JoinThread(LinkGraphJob *job);
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 void Run(void *j);
static void Clear();
void SpawnNext();
void JoinNext();
void SpawnAll();
/**
* Queue a link graph for execution.
* @param lg Link graph to be queued.
*/
void Queue(LinkGraph *lg)
{
assert(LinkGraph::Get(lg->index) == lg);
this->schedule.push_back(lg);
}
/**
* Remove a link graph from the execution queue.
* @param lg Link graph to be removed.
*/
void Unqueue(LinkGraph *lg) { this->schedule.remove(lg); }
};
#endif /* LINKGRAPHSCHEDULE_H */

View File

@ -27,6 +27,7 @@
#include "window_func.h"
#include "core/pool_type.hpp"
#include "game/game.hpp"
#include "linkgraph/linkgraphschedule.h"
extern TileIndex _cur_tileloop_tile;
@ -68,6 +69,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
InitializeOldNames();
}
LinkGraphSchedule::Clear();
PoolBase::Clean(PT_NORMAL);
ResetPersistentNewGRFData();

View File

@ -63,6 +63,8 @@
#include "subsidy_func.h"
#include "linkgraph/linkgraphschedule.h"
#include <stdarg.h>
@ -297,6 +299,7 @@ static void ShutdownGame()
free(_config_file);
#endif
LinkGraphSchedule::Clear();
PoolBase::Clean(PT_ALL);
/* No NewGRFs were loaded when it was still bootstrapping. */