Skip to content
Permalink
Browse files

Codechange: Replace custom thread code with C++11 thread objects.

We assume a conforming C++11 compiler environment that has a valid <thread>-header.
Failure to run a real thread is handled gracefully.
  • Loading branch information...
michicc committed Mar 17, 2019
1 parent 05f4e73 commit 05bc2ed7cbe07cb4cd535932f10778b35f72e944
@@ -1334,8 +1334,7 @@
<ResourceCompile Include="..\src\os\windows\ottdres.rc" />
<ClCompile Include="..\src\os\windows\string_uniscribe.cpp" />
<ClCompile Include="..\src\os\windows\win32.cpp" />
<ClInclude Include="..\src\thread\thread.h" />
<ClCompile Include="..\src\thread\thread_win32.cpp" />
<ClInclude Include="..\src\thread.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />
@@ -3090,12 +3090,9 @@
<ClCompile Include="..\src\os\windows\win32.cpp">
<Filter>Windows files</Filter>
</ClCompile>
<ClInclude Include="..\src\thread\thread.h">
<ClInclude Include="..\src\thread.h">
<Filter>Threading</Filter>
</ClInclude>
<ClCompile Include="..\src\thread\thread_win32.cpp">
<Filter>Threading</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />
@@ -1334,8 +1334,7 @@
<ResourceCompile Include="..\src\os\windows\ottdres.rc" />
<ClCompile Include="..\src\os\windows\string_uniscribe.cpp" />
<ClCompile Include="..\src\os\windows\win32.cpp" />
<ClInclude Include="..\src\thread\thread.h" />
<ClCompile Include="..\src\thread\thread_win32.cpp" />
<ClInclude Include="..\src\thread.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />
@@ -3090,12 +3090,9 @@
<ClCompile Include="..\src\os\windows\win32.cpp">
<Filter>Windows files</Filter>
</ClCompile>
<ClInclude Include="..\src\thread\thread.h">
<ClInclude Include="..\src\thread.h">
<Filter>Threading</Filter>
</ClInclude>
<ClCompile Include="..\src\thread\thread_win32.cpp">
<Filter>Threading</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />
@@ -1334,8 +1334,7 @@
<ResourceCompile Include="..\src\os\windows\ottdres.rc" />
<ClCompile Include="..\src\os\windows\string_uniscribe.cpp" />
<ClCompile Include="..\src\os\windows\win32.cpp" />
<ClInclude Include="..\src\thread\thread.h" />
<ClCompile Include="..\src\thread\thread_win32.cpp" />
<ClInclude Include="..\src\thread.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />
@@ -3090,12 +3090,9 @@
<ClCompile Include="..\src\os\windows\win32.cpp">
<Filter>Windows files</Filter>
</ClCompile>
<ClInclude Include="..\src\thread\thread.h">
<ClInclude Include="..\src\thread.h">
<Filter>Threading</Filter>
</ClInclude>
<ClCompile Include="..\src\thread\thread_win32.cpp">
<Filter>Threading</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />
@@ -1173,17 +1173,4 @@ sound/null_s.cpp
#end

# Threading
thread/thread.h
#if USE_THREADS
#if WIN32
thread/thread_win32.cpp
#else
#if OS2
thread/thread_os2.cpp
#else
thread/thread_pthread.cpp
#end
#end
#else
thread/thread_none.cpp
#end
thread.h
@@ -34,7 +34,7 @@
#include "game/game.hpp"
#include "game/game_instance.hpp"
#include "string_func.h"
#include "thread/thread.h"
#include "thread.h"

#include "safeguards.h"

@@ -94,7 +94,7 @@ static void CleanupGeneration()
/**
* The internal, real, generate function.
*/
static void _GenerateWorld(void *)
static void _GenerateWorld()
{
/* Make sure everything is done via OWNER_NONE. */
Backup<CompanyByte> _cur_company(_current_company, OWNER_NONE, FILE_LINE);
@@ -242,14 +242,12 @@ void GenerateWorldSetAbortCallback(GWAbortProc *proc)
*/
void WaitTillGeneratedWorld()
{
if (_gw.thread == NULL) return;
if (!_gw.thread.joinable()) return;

_modal_progress_work_mutex.unlock();
_modal_progress_paint_mutex.unlock();
_gw.quit_thread = true;
_gw.thread->Join();
delete _gw.thread;
_gw.thread = NULL;
_gw.thread.join();
_gw.threaded = false;
_modal_progress_work_mutex.lock();
_modal_progress_paint_mutex.lock();
@@ -284,7 +282,7 @@ void HandleGeneratingWorldAbortion()

CleanupGeneration();

if (_gw.thread != NULL) _gw.thread->Exit();
if (_gw.thread.joinable() && _gw.thread.get_id() == std::this_thread::get_id()) throw OTTDThreadExitSignal();

SwitchToMode(_switch_mode);
}
@@ -326,17 +324,13 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
SetupColoursAndInitialWindow();
SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0);

if (_gw.thread != NULL) {
_gw.thread->Join();
delete _gw.thread;
_gw.thread = NULL;
}
if (_gw.thread.joinable()) _gw.thread.join();

if (!UseThreadedModelProgress() || !VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&_GenerateWorld, NULL, &_gw.thread, "ottd:genworld")) {
if (!UseThreadedModelProgress() || !VideoDriver::GetInstance()->HasGUI() || !StartNewThread(&_gw.thread, "ottd:genworld", &_GenerateWorld)) {
DEBUG(misc, 1, "Cannot create genworld thread, reverting to single-threaded mode");
_gw.threaded = false;
_modal_progress_work_mutex.unlock();
_GenerateWorld(NULL);
_GenerateWorld();
_modal_progress_work_mutex.lock();
return;
}
@@ -13,6 +13,7 @@
#define GENWORLD_H

#include "company_type.h"
#include <thread>

/** Constants related to world generation */
enum LandscapeGenerator {
@@ -61,7 +62,7 @@ struct GenWorldInfo {
uint size_y; ///< Y-size of the map
GWDoneProc *proc; ///< Proc that is called when done (can be NULL)
GWAbortProc *abortp; ///< Proc that is called when aborting (can be NULL)
class ThreadObject *thread; ///< The thread we are in (can be NULL)
std::thread thread; ///< The thread we are in (joinable if a thread was created)
};

/** Current stage of world generation process */
@@ -39,7 +39,6 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig) :
* This is on purpose. */
link_graph(orig),
settings(_settings_game.linkgraph),
thread(NULL),
join_date(_date + _settings_game.linkgraph.recalc_time)
{
}
@@ -61,8 +60,7 @@ void LinkGraphJob::EraseFlows(NodeID from)
*/
void LinkGraphJob::SpawnThread()
{
if (!ThreadObject::New(&(LinkGraphSchedule::Run), this, &this->thread, "ottd:linkgraph")) {
this->thread = NULL;
if (!StartNewThread(&this->thread, "ottd:linkgraph", &(LinkGraphSchedule::Run), this)) {
/* 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.
@@ -79,10 +77,8 @@ void LinkGraphJob::SpawnThread()
*/
void LinkGraphJob::JoinThread()
{
if (this->thread != NULL) {
this->thread->Join();
delete this->thread;
this->thread = NULL;
if (this->thread.joinable()) {
this->thread.join();
}
}

@@ -12,7 +12,7 @@
#ifndef LINKGRAPHJOB_H
#define LINKGRAPHJOB_H

#include "../thread/thread.h"
#include "../thread.h"
#include "linkgraph.h"
#include <list>

@@ -59,7 +59,7 @@ class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
protected:
const LinkGraph link_graph; ///< Link graph to by analyzed. Is copied when job is started and mustn't be modified later.
const LinkGraphSettings settings; ///< Copy of _settings_game.linkgraph at spawn time.
ThreadObject *thread; ///< Thread the job is running in or NULL if it's running in the main thread.
std::thread thread; ///< Thread the job is running in or a default-constructed thread if it's running in the main thread.
Date join_date; ///< Date when the job is to be joined.
NodeAnnotationVector nodes; ///< Extra node data necessary for link graph calculation.
EdgeAnnotationMatrix edges; ///< Extra edge data necessary for link graph calculation.
@@ -266,7 +266,7 @@ class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
* Bare constructor, only for save/load. link_graph, join_date and actually
* settings have to be brutally const-casted in order to populate them.
*/
LinkGraphJob() : settings(_settings_game.linkgraph), thread(NULL),
LinkGraphJob() : settings(_settings_game.linkgraph),
join_date(INVALID_DATE) {}

LinkGraphJob(const LinkGraph &orig);
@@ -69,13 +69,11 @@ void LinkGraphSchedule::JoinNext()
}

/**
* Run all handlers for the given Job. This method is tailored to
* ThreadObject::New.
* @param j Pointer to a link graph job.
* Run all handlers for the given Job.
* @param job Pointer to a link graph job.
*/
/* static */ void LinkGraphSchedule::Run(void *j)
/* static */ void LinkGraphSchedule::Run(LinkGraphJob *job)
{
LinkGraphJob *job = (LinkGraphJob *)j;
for (uint i = 0; i < lengthof(instance.handlers); ++i) {
instance.handlers[i]->Run(*job);
}
@@ -53,7 +53,7 @@ class LinkGraphSchedule {
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 Run(LinkGraphJob *job);
static void Clear();

void SpawnNext();
@@ -19,7 +19,7 @@
#include "../debug.h"
#include "../os/windows/win32.h"
#include "../core/mem_func.hpp"
#include "../thread/thread.h"
#include "../thread.h"
#include "../fileio_func.h"
#include "../base_media_base.h"
#include "dmusic.h"
@@ -139,7 +139,7 @@ static struct {
} _playback;

/** Handle to our worker thread. */
static ThreadObject *_dmusic_thread = NULL;
static std::thread _dmusic_thread;
/** Event to signal the thread that it should look at a state change. */
static HANDLE _thread_event = NULL;
/** Lock access to playback data that is not thread-safe. */
@@ -597,7 +597,7 @@ static void TransmitNotesOff(IDirectMusicBuffer *buffer, REFERENCE_TIME block_ti
Sleep(Clamp((block_time - cur_time) / MS_TO_REFTIME, 5, 1000));
}

static void MidiThreadProc(void *)
static void MidiThreadProc()
{
DEBUG(driver, 2, "DMusic: Entering playback thread");

@@ -1169,7 +1169,7 @@ const char *MusicDriver_DMusic::Start(const char * const *parm)
_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (_thread_event == NULL) return "Can't create thread shutdown event";

if (!ThreadObject::New(&MidiThreadProc, this, &_dmusic_thread, "ottd:dmusic")) return "Can't create MIDI output thread";
if (!StartNewThread(&_dmusic_thread, "ottd:dmusic", &MidiThreadProc)) return "Can't create MIDI output thread";

return NULL;
}
@@ -1183,10 +1183,10 @@ MusicDriver_DMusic::~MusicDriver_DMusic()

void MusicDriver_DMusic::Stop()
{
if (_dmusic_thread != NULL) {
if (_dmusic_thread.joinable()) {
_playback.shutdown = true;
SetEvent(_thread_event);
_dmusic_thread->Join();
_dmusic_thread.join();
}

/* Unloaded any instruments we loaded. */
@@ -63,15 +63,14 @@ class NetworkTCPSocketHandler : public NetworkSocketHandler {
*/
class TCPConnecter {
private:
class ThreadObject *thread; ///< Thread used to create the TCP connection
bool connected; ///< Whether we succeeded in making the connection
bool aborted; ///< Whether we bailed out (i.e. connection making failed)
bool killed; ///< Whether we got killed
SOCKET sock; ///< The socket we're connecting with

void Connect();

static void ThreadEntry(void *param);
static void ThreadEntry(TCPConnecter *param);

protected:
/** Address we're connecting to */
@@ -12,7 +12,7 @@
*/

#include "../../stdafx.h"
#include "../../thread/thread.h"
#include "../../thread.h"

#include "tcp.h"

@@ -33,7 +33,7 @@ TCPConnecter::TCPConnecter(const NetworkAddress &address) :
address(address)
{
_tcp_connecters.push_back(this);
if (!ThreadObject::New(TCPConnecter::ThreadEntry, this, &this->thread, "ottd:tcp")) {
if (!StartNewThread(NULL, "ottd:tcp", &TCPConnecter::ThreadEntry, this)) {
this->Connect();
}
}
@@ -53,9 +53,9 @@ void TCPConnecter::Connect()
* Entry point for the new threads.
* @param param the TCPConnecter instance to call Connect on.
*/
/* static */ void TCPConnecter::ThreadEntry(void *param)
/* static */ void TCPConnecter::ThreadEntry(TCPConnecter *param)
{
static_cast<TCPConnecter*>(param)->Connect();
param->Connect();
}

/**
@@ -14,7 +14,6 @@

#include "network_internal.h"
#include "core/tcp_listen.h"
#include "../thread/thread.h"

class ServerNetworkGameSocketHandler;
/** Make the code look slightly nicer/simpler. */
Oops, something went wrong.

0 comments on commit 05bc2ed

Please sign in to comment.
You can’t perform that action at this time.