Index: ps/trunk/source/graphics/MapGenerator.h =================================================================== --- ps/trunk/source/graphics/MapGenerator.h +++ ps/trunk/source/graphics/MapGenerator.h @@ -28,6 +28,7 @@ #include #include #include +#include class CMapGeneratorWorker; @@ -179,7 +180,7 @@ /** * Perform map generation in an independent thread. */ - static void* RunThread(void* data); + static void* RunThread(CMapGeneratorWorker* self); /** * Perform the map generation. @@ -229,7 +230,7 @@ /** * Holds the mapgeneration thread identifier. */ - pthread_t m_WorkerThread; + std::thread m_WorkerThread; /** * Avoids thread synchronization issues. Index: ps/trunk/source/graphics/MapGenerator.cpp =================================================================== --- ps/trunk/source/graphics/MapGenerator.cpp +++ ps/trunk/source/graphics/MapGenerator.cpp @@ -66,7 +66,7 @@ CMapGeneratorWorker::~CMapGeneratorWorker() { // Wait for thread to end - pthread_join(m_WorkerThread, NULL); + m_WorkerThread.join(); } void CMapGeneratorWorker::Initialize(const VfsPath& scriptFile, const std::string& settings) @@ -79,17 +79,14 @@ m_Settings = settings; // Launch the worker thread - int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); - ENSURE(ret == 0); + m_WorkerThread = std::thread(RunThread, this); } -void* CMapGeneratorWorker::RunThread(void *data) +void* CMapGeneratorWorker::RunThread(CMapGeneratorWorker* self) { debug_SetThreadName("MapGenerator"); g_Profiler2.RegisterCurrentThread("MapGenerator"); - CMapGeneratorWorker* self = static_cast(data); - shared_ptr mapgenRuntime = ScriptInterface::CreateRuntime(g_ScriptRuntime, RMS_RUNTIME_SIZE); // Enable the script to be aborted Index: ps/trunk/source/graphics/TextureConverter.h =================================================================== --- ps/trunk/source/graphics/TextureConverter.h +++ ps/trunk/source/graphics/TextureConverter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,11 +19,12 @@ #define INCLUDED_TEXTURECONVERTER #include "lib/file/vfs/vfs.h" -#include "lib/posix/posix_pthread.h" #include "lib/external_libraries/libsdl.h" #include "TextureManager.h" +#include + class MD5; /** @@ -199,13 +200,13 @@ bool IsBusy(); private: - static void* RunThread(void* data); + static void RunThread(CTextureConverter* data); PIVFS m_VFS; bool m_HighQuality; - pthread_t m_WorkerThread; - pthread_mutex_t m_WorkerMutex; + std::thread m_WorkerThread; + std::mutex m_WorkerMutex; SDL_sem* m_WorkerSem; struct ConversionRequest; Index: ps/trunk/source/graphics/TextureConverter.cpp =================================================================== --- ps/trunk/source/graphics/TextureConverter.cpp +++ ps/trunk/source/graphics/TextureConverter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -292,11 +292,7 @@ m_WorkerSem = SDL_CreateSemaphore(0); ENSURE(m_WorkerSem); - ret = pthread_mutex_init(&m_WorkerMutex, NULL); - ENSURE(ret == 0); - - ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); - ENSURE(ret == 0); + m_WorkerThread = std::thread(RunThread, this); // Maybe we should share some centralised pool of worker threads? // For now we'll just stick with a single thread for this specific use. @@ -305,19 +301,19 @@ CTextureConverter::~CTextureConverter() { // Tell the thread to shut down - pthread_mutex_lock(&m_WorkerMutex); - m_Shutdown = true; - pthread_mutex_unlock(&m_WorkerMutex); + { + std::lock_guard lock(m_WorkerMutex); + m_Shutdown = true; + } // Wake it up so it sees the notification SDL_SemPost(m_WorkerSem); // Wait for it to shut down cleanly - pthread_join(m_WorkerThread, NULL); + m_WorkerThread.join(); // Clean up resources SDL_DestroySemaphore(m_WorkerSem); - pthread_mutex_destroy(&m_WorkerMutex); } bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath& src, const VfsPath& dest, const Settings& settings) @@ -463,9 +459,10 @@ delete[] rgba; } - pthread_mutex_lock(&m_WorkerMutex); - m_RequestQueue.push_back(request); - pthread_mutex_unlock(&m_WorkerMutex); + { + std::lock_guard lock(m_WorkerMutex); + m_RequestQueue.push_back(request); + } // Wake up the worker thread SDL_SemPost(m_WorkerSem); @@ -484,13 +481,14 @@ shared_ptr result; // Grab the first result (if any) - pthread_mutex_lock(&m_WorkerMutex); - if (!m_ResultQueue.empty()) { - result = m_ResultQueue.front(); - m_ResultQueue.pop_front(); + std::lock_guard lock(m_WorkerMutex); + if (!m_ResultQueue.empty()) + { + result = m_ResultQueue.front(); + m_ResultQueue.pop_front(); + } } - pthread_mutex_unlock(&m_WorkerMutex); if (!result) { @@ -530,20 +528,17 @@ bool CTextureConverter::IsBusy() { - pthread_mutex_lock(&m_WorkerMutex); + std::lock_guard lock(m_WorkerMutex); bool busy = !m_RequestQueue.empty(); - pthread_mutex_unlock(&m_WorkerMutex); return busy; } -void* CTextureConverter::RunThread(void* data) +void CTextureConverter::RunThread(CTextureConverter* textureConverter) { debug_SetThreadName("TextureConverter"); g_Profiler2.RegisterCurrentThread("texconv"); - CTextureConverter* textureConverter = static_cast(data); - #if CONFIG2_NVTT // Wait until the main thread wakes us up @@ -552,17 +547,17 @@ g_Profiler2.RecordSyncMarker(); PROFILE2_EVENT("wakeup"); - pthread_mutex_lock(&textureConverter->m_WorkerMutex); - if (textureConverter->m_Shutdown) + shared_ptr request; + { - pthread_mutex_unlock(&textureConverter->m_WorkerMutex); - break; + std::lock_guard lock(textureConverter->m_WorkerMutex); + if (textureConverter->m_Shutdown) + break; + // If we weren't woken up for shutdown, we must have been woken up for + // a new request, so grab it from the queue + request = textureConverter->m_RequestQueue.front(); + textureConverter->m_RequestQueue.pop_front(); } - // If we weren't woken up for shutdown, we must have been woken up for - // a new request, so grab it from the queue - shared_ptr request = textureConverter->m_RequestQueue.front(); - textureConverter->m_RequestQueue.pop_front(); - pthread_mutex_unlock(&textureConverter->m_WorkerMutex); // Set up the result object shared_ptr result(new ConversionResult()); @@ -595,12 +590,9 @@ result->output.buffer[80] &= ~0x40; // DDPF_RGB in DDS_PIXELFORMAT.dwFlags // Push the result onto the queue - pthread_mutex_lock(&textureConverter->m_WorkerMutex); + std::lock_guard lock(textureConverter->m_WorkerMutex); textureConverter->m_ResultQueue.push_back(result); - pthread_mutex_unlock(&textureConverter->m_WorkerMutex); } #endif - - return NULL; } Index: ps/trunk/source/lib/timer.cpp =================================================================== --- ps/trunk/source/lib/timer.cpp +++ ps/trunk/source/lib/timer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -82,16 +82,15 @@ #endif } -static pthread_mutex_t ensure_monotonic_mutex = PTHREAD_MUTEX_INITIALIZER; +static std::mutex ensure_monotonic_mutex; // NB: does not guarantee strict monotonicity - callers must avoid // dividing by the difference of two equal times. static void EnsureMonotonic(double& newTime) { - pthread_mutex_lock(&ensure_monotonic_mutex); + std::lock_guard lock(ensure_monotonic_mutex); static double maxTime; maxTime = std::max(maxTime, newTime); newTime = maxTime; - pthread_mutex_unlock(&ensure_monotonic_mutex); } Index: ps/trunk/source/ps/UserReport.cpp =================================================================== --- ps/trunk/source/ps/UserReport.cpp +++ ps/trunk/source/ps/UserReport.cpp @@ -30,11 +30,11 @@ #include "ps/ConfigDB.h" #include "ps/Filesystem.h" #include "ps/Profiler2.h" -#include "ps/ThreadUtil.h" #include #include #include +#include #define DEBUG_UPLOADS 0 @@ -143,8 +143,7 @@ m_WorkerSem = SDL_CreateSemaphore(0); ENSURE(m_WorkerSem); - int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); - ENSURE(ret == 0); + m_WorkerThread = std::thread(RunThread, this); } ~CUserReporterWorker() @@ -191,7 +190,7 @@ // Wait for it to shut down cleanly // TODO: should have a timeout in case of network hangs - pthread_join(m_WorkerThread, NULL); + m_WorkerThread.join(); return true; } @@ -236,14 +235,12 @@ } private: - static void* RunThread(void* data) + static void RunThread(CUserReporterWorker* data) { debug_SetThreadName("CUserReportWorker"); g_Profiler2.RegisterCurrentThread("userreport"); - static_cast(data)->Run(); - - return NULL; + data->Run(); } void Run() @@ -489,7 +486,7 @@ private: // Thread-related members: - pthread_t m_WorkerThread; + std::thread m_WorkerThread; std::mutex m_WorkerMutex; SDL_sem* m_WorkerSem; Index: ps/trunk/source/soundmanager/SoundManager.cpp =================================================================== --- ps/trunk/source/soundmanager/SoundManager.cpp +++ ps/trunk/source/soundmanager/SoundManager.cpp @@ -32,6 +32,8 @@ #include "ps/Profiler2.h" #include "ps/XML/Xeromyces.h" +#include + ISoundManager* g_SoundManager = NULL; #define SOURCE_NUM 64 @@ -49,8 +51,7 @@ m_DeadItems = new ItemsList; m_Shutdown = false; - int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); - ENSURE(ret == 0); + m_WorkerThread = std::thread(RunThread, this); } ~CSoundManagerWorker() @@ -76,7 +77,7 @@ } - pthread_join(m_WorkerThread, NULL); + m_WorkerThread.join(); return true; } @@ -103,14 +104,12 @@ } private: - static void* RunThread(void* data) + static void RunThread(CSoundManagerWorker* data) { debug_SetThreadName("CSoundManagerWorker"); g_Profiler2.RegisterCurrentThread("soundmanager"); - static_cast(data)->Run(); - - return NULL; + data->Run(); } void Run() @@ -168,7 +167,7 @@ private: // Thread-related members: - pthread_t m_WorkerThread; + std::thread m_WorkerThread; std::mutex m_WorkerMutex; std::mutex m_DeadItemsMutex; Index: ps/trunk/source/tools/atlas/GameInterface/GameLoop.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/GameLoop.cpp +++ ps/trunk/source/tools/atlas/GameInterface/GameLoop.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -17,6 +17,8 @@ #include "precompiled.h" +#include + #include "GameLoop.h" #include "MessagePasserImpl.h" @@ -37,6 +39,7 @@ #include "ps/DllLoader.h" #include "ps/Filesystem.h" #include "ps/Profile.h" +#include "ps/ThreadUtil.h" #include "ps/GameSetup/Paths.h" #include "renderer/Renderer.h" @@ -98,7 +101,7 @@ while (more && timer_Time() - startTime < maxTime); } -static void* RunEngine(void* data) +static void RunEngine(const CmdLineArgs& args) { debug_SetThreadName("engine_thread"); @@ -107,8 +110,6 @@ g_Profiler2.RegisterCurrentThread("atlasmain"); - const CmdLineArgs args = *reinterpret_cast(data); - MessagePasserImpl* msgPasser = (MessagePasserImpl*)AtlasMessage::g_MessagePasser; // Register all the handlers for message which might be passed back @@ -267,8 +268,6 @@ SDL_Delay(0); } } - - return NULL; } bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll) @@ -309,15 +308,14 @@ Atlas_SetConfigDirectory(paths.Config().string().c_str()); // Run the engine loop in a new thread - pthread_t engineThread; - pthread_create(&engineThread, NULL, RunEngine, reinterpret_cast(const_cast(&args))); + std::thread engineThread = std::thread(RunEngine, std::ref(args)); // Start Atlas UI on main thread // (required for wxOSX/Cocoa compatibility - see http://trac.wildfiregames.com/ticket/500) Atlas_StartWindow(L"ScenarioEditor"); // Wait for the engine to exit - pthread_join(engineThread, NULL); + engineThread.join(); // TODO: delete all remaining messages, to avoid memory leak warnings