From 2c05c49a04aa838047417825c289958efb59ee3c Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 27 Jan 2011 20:47:58 +0000 Subject: [PATCH] Replaced Common::Thread with a partial implementation of std::thread. (rvalue references are used if available, is used if possible) Eliminates the need to use dynamic memory allocation for threads, so it's impossible to forget to delete a thread or set a pointer to NULL. Enables use of type-safe thread functions, no need to cast to and from void*. I've made sure the code compiles in vs08 and tested the functionality of "StdThread.h" on Linux so I'm hoping everything will work :p. In the future "StdThread.h" can be removed (maybe when OS X ships with gcc 4.4 and vs2015 is released :p). git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6933 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/AudioCommon/Src/AOSoundStream.cpp | 10 +- Source/Core/AudioCommon/Src/AOSoundStream.h | 2 +- Source/Core/AudioCommon/Src/DSoundStream.cpp | 10 +- Source/Core/AudioCommon/Src/DSoundStream.h | 2 +- Source/Core/AudioCommon/Src/OpenALStream.cpp | 11 +- Source/Core/AudioCommon/Src/OpenALStream.h | 4 +- Source/Core/Common/Common.vcproj | 4 + Source/Core/Common/Common.vcxproj | 1 + Source/Core/Common/Src/StdThread.h | 298 ++++++++++++++++++ Source/Core/Common/Src/Thread.cpp | 175 +++------- Source/Core/Common/Src/Thread.h | 90 +----- Source/Core/Core/Src/Core.cpp | 44 ++- Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp | 35 +- Source/Core/Core/Src/HW/EXI_DeviceGecko.h | 6 +- .../Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp | 32 +- .../Core/Core/Src/HW/EXI_DeviceMemoryCard.h | 2 +- Source/Core/Core/Src/HW/SI_DeviceGBA.cpp | 16 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 38 +-- Source/Core/Core/Src/State.cpp | 15 +- Source/Core/DolphinWX/Src/NetPlay.cpp | 5 +- Source/Core/DolphinWX/Src/NetPlay.h | 7 +- Source/Core/DolphinWX/Src/NetPlayClient.cpp | 5 +- Source/Core/DolphinWX/Src/NetPlayServer.cpp | 5 +- Source/Core/InputCommon/Src/UDPWiimote.cpp | 19 +- Source/Core/InputCommon/Src/UDPWiimote.h | 2 +- Source/Plugins/Plugin_DSP_LLE/Src/main.cpp | 10 +- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 7 +- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h | 2 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 23 +- 29 files changed, 484 insertions(+), 396 deletions(-) create mode 100644 Source/Core/Common/Src/StdThread.h diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.cpp b/Source/Core/AudioCommon/Src/AOSoundStream.cpp index cff38d1c7f..a1bc0e0a76 100644 --- a/Source/Core/AudioCommon/Src/AOSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/AOSoundStream.cpp @@ -54,10 +54,9 @@ void AOSound::SoundLoop() } } -void *soundThread(void *args) +void soundThread(AOSound *aosound) { - ((AOSound *)args)->SoundLoop(); - return NULL; + aosound->SoundLoop(); } bool AOSound::Start() @@ -66,7 +65,7 @@ bool AOSound::Start() soundSyncEvent.Init(); - thread = new Common::Thread(soundThread, (void *)this); + thread = std::thread(soundThread, this); return true; } @@ -81,8 +80,7 @@ void AOSound::Stop() soundSyncEvent.Set(); soundCriticalSection.Enter(); - delete thread; - thread = NULL; + thread.join(); if (device) ao_close(device); diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.h b/Source/Core/AudioCommon/Src/AOSoundStream.h index afba7b363f..57a883aa83 100644 --- a/Source/Core/AudioCommon/Src/AOSoundStream.h +++ b/Source/Core/AudioCommon/Src/AOSoundStream.h @@ -29,7 +29,7 @@ class AOSound : public SoundStream { #if defined(HAVE_AO) && HAVE_AO - Common::Thread *thread; + std::thread thread; Common::CriticalSection soundCriticalSection; Common::Event soundSyncEvent; diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp index 3ebfa15659..7b17431cbc 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp @@ -91,10 +91,9 @@ bool DSound::WriteDataToBuffer(DWORD dwOffset, // Our own write } // The audio thread. -THREAD_RETURN soundThread(void* args) +void soundThread(DSound* dsound) { - (reinterpret_cast(args))->SoundLoop(); - return 0; + dsound->SoundLoop(); } void DSound::SoundLoop() @@ -138,7 +137,7 @@ bool DSound::Start() dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); memset(p1, 0, num1); dsBuffer->Unlock(p1, num1, 0, 0); - thread = new Common::Thread(soundThread, (void *)this); + thread = std::thread(soundThread, this); return true; } @@ -179,8 +178,7 @@ void DSound::Stop() // kick the thread if it's waiting soundSyncEvent.Set(); - delete thread; - thread = NULL; + thread.join(); dsBuffer->Stop(); dsBuffer->Release(); ds->Release(); diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h index adbeaeb468..73d6fcbae3 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.h +++ b/Source/Core/AudioCommon/Src/DSoundStream.h @@ -31,7 +31,7 @@ class DSound : public SoundStream { #ifdef _WIN32 - Common::Thread *thread; + std::thread thread; Common::EventEx soundSyncEvent; void *hWnd; diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index e92d1cdc27..908f1c0099 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -44,8 +44,7 @@ bool OpenALStream::Start() if (pContext) { alcMakeContextCurrent(pContext); - thread = new Common::Thread( - OpenALStream::ThreadFunc, (void *)this); + thread = std::thread(OpenALStream::ThreadFunc, this); bReturn = true; } else @@ -75,8 +74,7 @@ void OpenALStream::Stop() // kick the thread if it's waiting soundSyncEvent.Set(); - delete thread; - thread = NULL; + thread.join(); alSourceStop(uiSource); alSourcei(uiSource, AL_BUFFER, 0); @@ -123,10 +121,9 @@ void OpenALStream::Clear(bool mute) } } -THREAD_RETURN OpenALStream::ThreadFunc(void* args) +void OpenALStream::ThreadFunc(OpenALStream* alstream) { - (reinterpret_cast(args))->SoundLoop(); - return 0; + alstream->SoundLoop(); } void OpenALStream::SoundLoop() diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index 82a1eca1eb..7475fcfe83 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -58,10 +58,10 @@ public: virtual bool usesMixer() const { return true; } virtual void Update(); - static THREAD_RETURN ThreadFunc(void* args); + static void ThreadFunc(OpenALStream* args); private: - Common::Thread *thread; + std::thread thread; Common::EventEx soundSyncEvent; short realtimeBuffer[OAL_MAX_SAMPLES * 2]; diff --git a/Source/Core/Common/Common.vcproj b/Source/Core/Common/Common.vcproj index 1b2b05a32b..1667d5711f 100644 --- a/Source/Core/Common/Common.vcproj +++ b/Source/Core/Common/Common.vcproj @@ -845,6 +845,10 @@ RelativePath=".\Src\stdafx.h" > + + diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 5bc6c63a10..4a15c7d641 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -322,6 +322,7 @@ + diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h new file mode 100644 index 0000000000..859c66902c --- /dev/null +++ b/Source/Core/Common/Src/StdThread.h @@ -0,0 +1,298 @@ + +#ifndef STD_THREAD_H_ +#define STD_THREAD_H_ + +#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) +#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +// GCC 4.4 provides +#include +#else + +// partial std::thread implementation for win32/pthread + +#include + +#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) +#define USE_RVALUE_REFERENCES +#endif + +#if defined(_WIN32) +// WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +#if defined(_MSC_VER) && defined(_MT) +// When linking with LIBCMT (the multithreaded C library), Microsoft recommends +// using _beginthreadex instead of CreateThread. +#define USE_BEGINTHREADEX +#include +#endif + +#ifdef USE_BEGINTHREADEX +#define THREAD_ID unsigned +#define THREAD_RETURN unsigned __stdcall +#else +#define THREAD_ID DWORD +#define THREAD_RETURN DWORD WINAPI +#endif +#define THREAD_HANDLE HANDLE + +#else +// PTHREAD + +#include + +#ifndef _POSIX_THREADS +#error unsupported platform (no pthreads?) +#endif + +#include + +#define THREAD_ID pthread_t +#define THREAD_HANDLE pthread_t +#define THREAD_RETURN void* + +#endif + +namespace std +{ + +class thread +{ +public: + typedef THREAD_HANDLE native_handle_type; + + class id + { + friend class thread; + public: + id() : m_thread(0) {} + id(THREAD_ID _id) : m_thread(_id) {} + + bool operator==(const id& rhs) const + { + return m_thread == rhs.m_thread; + } + + bool operator!=(const id& rhs) const + { + return !(*this == rhs); + } + + bool operator<(const id& rhs) const + { + return m_thread < rhs.m_thread; + } + + private: + THREAD_ID m_thread; + }; + + // no variadic template support in msvc + //template + //thread(C&& func, A&&... args); + + template + thread(C func) + { + StartThread(new Func(func)); + } + + template + thread(C func, A arg) + { + StartThread(new FuncArg(func, arg)); + } + + thread() /*= default;*/ {} + +#ifdef USE_RVALUE_REFERENCES + thread(const thread&) /*= delete*/; + + thread(thread&& other) + { +#else + thread(const thread& t) + { + // ugly const_cast to get around lack of rvalue references + thread& other = const_cast(t); +#endif + swap(other); + } + +#ifdef USE_RVALUE_REFERENCES + thread& operator=(const thread&) /*= delete*/; + + thread& operator=(thread&& other) + { +#else + thread& operator=(const thread& t) + { + // ugly const_cast to get around lack of rvalue references + thread& other = const_cast(t); +#endif + if (joinable()) + detach(); + swap(other); + return *this; + } + + ~thread() + { + if (joinable()) + detach(); + } + + bool joinable() const + { + return m_id != id(); + } + + id get_id() const + { + return m_id; + } + + native_handle_type native_handle() + { +#ifdef _WIN32 + return m_handle; +#else + return m_id.m_thread; +#endif + } + + void join() + { +#ifdef _WIN32 + WaitForSingleObject(m_handle, INFINITE); + detach(); +#else + pthread_join(m_id.m_thread, NULL); + m_id = id(); +#endif + } + + void detach() + { +#ifdef _WIN32 + CloseHandle(m_handle); +#else + pthread_detach(m_id.m_thread); +#endif + m_id = id(); + } + + void swap(thread& other) + { + std::swap(m_id, other.m_id); +#ifdef _WIN32 + std::swap(m_handle, other.m_handle); +#endif + } + + static unsigned hardware_concurrency() + { +#ifdef _WIN32 + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return static_cast(sysinfo.dwNumberOfProcessors); +#else + return 0; +#endif + } + +private: + id m_id; + +#ifdef _WIN32 + native_handle_type m_handle; +#endif + + template + void StartThread(F* param) + { +#ifdef USE_BEGINTHREADEX + m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete, param, 0, &m_id.m_thread); +#elif defined(_WIN32) + m_handle = CreateThread(NULL, 0, &RunAndDelete, param, 0, &m_id.m_thread); +#else + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 1024 * 1024); + if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete, param)) + m_id = id(); +#endif + } + + template + class Func + { + public: + Func(C _func) : func(_func) {} + + void Run() { func(); } + + private: + C const func; + }; + + template + class FuncArg + { + public: + FuncArg(C _func, A _arg) : func(_func), arg(_arg) {} + + void Run() { func(arg); } + + private: + C const func; + A arg; + }; + + template + static THREAD_RETURN RunAndDelete(void* param) + { + static_cast(param)->Run(); + delete static_cast(param); + + return 0; + } +}; + +namespace this_thread +{ + +inline void yield() +{ +#ifdef _WIN32 + Sleep(1); +#else + usleep(1000 * 1); +#endif +} + +inline thread::id get_id() +{ +#ifdef _WIN32 + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +} // namespace this_thread + +} // namespace std + +#undef USE_RVALUE_REFERENCES +#undef USE_BEGINTHREADEX +#undef THREAD_ID +#undef THREAD_RETURN +#undef THREAD_HANDLE + +#endif +#endif diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 16624b6388..0238b14008 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -25,18 +25,28 @@ namespace Common { - - int Thread::CurrentId() - { + +int CurrentThreadId() +{ #ifdef _WIN32 - return GetCurrentThreadId(); + return GetCurrentThreadId(); #else - return 0; + return 0; #endif - } +} #ifdef _WIN32 - + +void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) +{ + SetThreadAffinityMask(thread, mask); +} + +void SetCurrentThreadAffinity(u32 mask) +{ + SetThreadAffinityMask(GetCurrentThread(), mask); +} + CriticalSection::CriticalSection(int spincount) { if (spincount) @@ -70,54 +80,6 @@ namespace Common LeaveCriticalSection(§ion); } - Thread::Thread(ThreadFunc function, void* arg) - : m_hThread(NULL), m_threadId(0) - { -#ifdef USE_BEGINTHREADEX - m_hThread = (HANDLE)_beginthreadex(NULL, 0, function, arg, 0, &m_threadId); -#else - m_hThread = CreateThread(NULL, 0, function, arg, 0, &m_threadId); -#endif - } - - Thread::~Thread() - { - WaitForDeath(); - } - - DWORD Thread::WaitForDeath(const int iWait) - { - if (m_hThread) - { - DWORD Wait = WaitForSingleObject(m_hThread, iWait); - CloseHandle(m_hThread); - m_hThread = NULL; - return Wait; - } - return NULL; - } - - void Thread::SetAffinity(int mask) - { - SetThreadAffinityMask(m_hThread, mask); - } - - void Thread::SetPriority(int priority) - { - SetThreadPriority(m_hThread, priority); - } - - void Thread::SetCurrentThreadAffinity(int mask) - { - SetThreadAffinityMask(GetCurrentThread(), mask); - } - - bool Thread::IsCurrentThread() - { - return GetCurrentThreadId() == m_threadId; - } - - EventEx::EventEx() { InterlockedExchange(&m_Lock, 1); @@ -300,7 +262,32 @@ namespace Common } #else // !WIN32, so must be POSIX threads - + +void LinuxSetThreadAffinity(pthread_t thread, u32 mask) +{ + // This is non-standard +#ifdef __linux__ + cpu_set_t cpu_set; + CPU_ZERO(&cpu_set); + + for (int i = 0; i != sizeof(mask) * 8; ++i) + if ((mask >> i) & 1) + CPU_SET(i, &cpu_set); + + pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); +#endif +} + +void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) +{ + LinuxSetThreadAffinity(thread, mask); +} + +void SetCurrentThreadAffinity(u32 mask) +{ + LinuxSetThreadAffinity(pthread_self(), mask); +} + static pthread_key_t threadname_key; static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT; @@ -344,82 +331,6 @@ namespace Common pthread_mutex_unlock(&mutex); #endif } - - - Thread::Thread(ThreadFunc function, void* arg) - : thread_id(0) - { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 1024 * 1024); - int ret = pthread_create(&thread_id, &attr, function, arg); - if (ret) ERROR_LOG(COMMON, "%s: pthread_create(%p, %p, %p, %p) failed: %s\n", - __FUNCTION__, &thread_id, &attr, function, arg, strerror(ret)); - - INFO_LOG(COMMON, "created new thread %lu (func=%p, arg=%p)\n", - (unsigned long)thread_id, function, arg); - } - - - Thread::~Thread() - { - WaitForDeath(); - } - - - void Thread::WaitForDeath() - { - if (thread_id) - { - void* exit_status; - int ret = pthread_join(thread_id, &exit_status); - if (ret) ERROR_LOG(COMMON, - "error joining thread %lu: %s\n", - (unsigned long)thread_id, strerror(ret)); - if (exit_status) - ERROR_LOG(COMMON, - "thread %lu exited with status %d\n", - (unsigned long)thread_id, *(int *)exit_status); - thread_id = 0; - } - } - - - void Thread::SetAffinity(int mask) - { - // This is non-standard -#ifdef __linux__ - cpu_set_t cpu_set; - CPU_ZERO(&cpu_set); - - for (unsigned int i = 0; i < sizeof(mask) * 8; i++) - { - if ((mask >> i) & 1){CPU_SET(i, &cpu_set);} - } - - pthread_setaffinity_np(thread_id, sizeof(cpu_set), &cpu_set); -#endif - } - - void Thread::SetCurrentThreadAffinity(int mask) - { -#ifdef __linux__ - cpu_set_t cpu_set; - CPU_ZERO(&cpu_set); - - for (size_t i = 0; i < sizeof(mask) * 8; i++) - { - if ((mask >> i) & 1){CPU_SET(i, &cpu_set);} - } - - pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set); -#endif - } - - bool Thread::IsCurrentThread() - { - return pthread_equal(pthread_self(), thread_id) != 0; - } void SleepCurrentThread(int ms) { diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index 5d4182f5e4..a11e1abf2c 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -18,37 +18,7 @@ #ifndef _THREAD_H_ #define _THREAD_H_ -#ifdef _WIN32 - -#if defined(_MSC_VER) && defined(_MT) -// When linking with LIBCMT (the multithreaded C library), Microsoft recommends -// using _beginthreadex instead of CreateThread. -#define USE_BEGINTHREADEX -#endif - -#define WIN32_LEAN_AND_MEAN -#include - -#ifdef USE_BEGINTHREADEX -#define THREAD_RETURN unsigned __stdcall -#else -#define THREAD_RETURN DWORD WINAPI -#endif - -#else - -#include -#define THREAD_RETURN void* -#include -#ifdef _POSIX_THREADS -#include -#elif GEKKO -#include -#else -#error unsupported platform (no pthreads?) -#endif - -#endif +#include "StdThread.h" // Don't include common.h here as it will break LogManager #include "CommonTypes.h" @@ -61,6 +31,8 @@ #define INFINITE 0xffffffff #endif +#include + //for gettimeofday and struct time(spec|val) #include #include @@ -69,6 +41,11 @@ namespace Common { + +int CurrentThreadId(); + +void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); +void SetCurrentThreadAffinity(u32 mask); class CriticalSection { @@ -88,57 +65,6 @@ namespace Common void Leave(); }; -#ifdef _WIN32 - -#ifdef USE_BEGINTHREADEX - typedef unsigned (__stdcall *ThreadFunc)(void* arg); -#else - typedef DWORD (WINAPI *ThreadFunc)(void* arg); -#endif - -#else - - typedef void* (*ThreadFunc)(void* arg); - -#endif - - class Thread - { - public: - Thread(ThreadFunc entry, void* arg); - ~Thread(); - - void SetAffinity(int mask); - static void SetCurrentThreadAffinity(int mask); - static int CurrentId(); - bool IsCurrentThread(); -#ifdef _WIN32 - void SetPriority(int priority); - DWORD WaitForDeath(const int iWait = INFINITE); -#else - void WaitForDeath(); -#endif - - private: - -#ifdef _WIN32 - - HANDLE m_hThread; -#ifdef USE_BEGINTHREADEX - unsigned m_threadId; -#else - DWORD m_threadId; -#endif - -#else - -#ifdef _POSIX_THREADS - pthread_t thread_id; -#endif - -#endif - }; - #ifdef _WIN32 // Event(WaitForSingleObject) is too expensive // as it always enters Ring0 regardless of the state of lock diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 2c6c104856..f375e65c19 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -95,7 +95,7 @@ TPeekMessages Callback_PeekMessages = NULL; TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL; // Function declarations -THREAD_RETURN EmuThread(void *pArg); +void EmuThread(); void Stop(); @@ -104,9 +104,9 @@ bool g_bHwInit = false; bool g_bRealWiimote = false; void *g_pWindowHandle = NULL; -Common::Thread* g_EmuThread = NULL; +std::thread g_EmuThread; -static Common::Thread* cpuThread = NULL; +static std::thread cpuThread; SCoreStartupParameter g_CoreStartupParameter; @@ -122,7 +122,7 @@ Common::Event cpuRunloopQuit; std::string StopMessage(bool bMainThread, std::string Message) { return StringFromFormat("Stop [%s %i]\t%s\t%s", - bMainThread ? "Main Thread" : "Video Thread", Common::Thread::CurrentId(), MemUsage().c_str(), Message.c_str()); + bMainThread ? "Main Thread" : "Video Thread", Common::CurrentThreadId(), MemUsage().c_str(), Message.c_str()); } // @@ -166,14 +166,14 @@ bool isRunning() bool IsRunningInCurrentThread() { - return isRunning() && ((cpuThread == NULL) || cpuThread->IsCurrentThread()); + return isRunning() && ((cpuThread.joinable()) || cpuThread.get_id() == std::this_thread::get_id()); } // This is called from the GUI thread. See the booting call schedule in // BootManager.cpp bool Init() { - if (g_EmuThread != NULL) + if (g_EmuThread.joinable()) { PanicAlertT("Emu Thread already running"); return false; @@ -195,7 +195,7 @@ bool Init() emuThreadGoing.Init(); // Start the emu thread - g_EmuThread = new Common::Thread(EmuThread, NULL); + g_EmuThread = std::thread(EmuThread); // Wait until the emu thread is running emuThreadGoing.MsgWait(); @@ -242,14 +242,12 @@ void Stop() // - Hammertime! Host_SetWaitCursor(false); WARN_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); - g_EmuThread->WaitForDeath(); - delete g_EmuThread; // Wait for emuthread to close. - g_EmuThread = 0; + g_EmuThread.join(); // Wait for emuthread to close. } // Create the CPU thread. which would be a CPU + Video thread in Single Core mode. -THREAD_RETURN CpuThread(void *pArg) +void CpuThread() { #ifdef __APPLE__ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -269,7 +267,7 @@ THREAD_RETURN CpuThread(void *pArg) } if (_CoreParameter.bLockThreads) - Common::Thread::SetCurrentThreadAffinity(1); // Force to first core + Common::SetCurrentThreadAffinity(1); // Force to first core if (_CoreParameter.bUseFastMem) { @@ -296,13 +294,13 @@ THREAD_RETURN CpuThread(void *pArg) #ifdef __APPLE__ [pool release]; #endif - return 0; + return; } // Initalize plugins and create emulation thread // Call browser: Init():g_EmuThread(). See the BootManager.cpp file description for a complete call schedule. -THREAD_RETURN EmuThread(void *pArg) +void EmuThread() { #ifdef __APPLE__ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -319,9 +317,9 @@ THREAD_RETURN EmuThread(void *pArg) if (_CoreParameter.bLockThreads) { if (cpu_info.num_cores > 3) - Common::Thread::SetCurrentThreadAffinity(4); // Force to third, non-HT core + Common::SetCurrentThreadAffinity(4); // Force to third, non-HT core else - Common::Thread::SetCurrentThreadAffinity(2); // Force to second core + Common::SetCurrentThreadAffinity(2); // Force to second core } INFO_LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "Gamecube"); @@ -420,7 +418,7 @@ THREAD_RETURN EmuThread(void *pArg) PowerPC::SetMode(PowerPC::MODE_INTERPRETER); // Spawn the CPU thread - _dbg_assert_(OSHLE, cpuThread == NULL); + _dbg_assert_(OSHLE, !cpuThread.joinable()); // ENTER THE VIDEO THREAD LOOP if (_CoreParameter.bCPUThread) { @@ -428,7 +426,7 @@ THREAD_RETURN EmuThread(void *pArg) // and then takes over and becomes the video thread Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent - cpuThread = new Common::Thread(CpuThread, pArg); + cpuThread = std::thread(CpuThread); Common::SetCurrentThreadName("Video thread"); // Update the window again because all stuff is initialized @@ -444,7 +442,7 @@ THREAD_RETURN EmuThread(void *pArg) // Without this extra thread, the video plugin window hangs in single // core mode since noone is pumping messages. - cpuThread = new Common::Thread(CpuThread, pArg); + cpuThread = std::thread(CpuThread); Common::SetCurrentThreadName("Emuthread - Idle"); // Update the window again because all stuff is initialized @@ -475,13 +473,10 @@ THREAD_RETURN EmuThread(void *pArg) // At this point, the CpuThread has already returned in SC mode. // But it may still be waiting in Dual Core mode. - if (cpuThread) + if (cpuThread.joinable()) { // There is a CPU thread - join it. - cpuThread->WaitForDeath(); - delete cpuThread; - // Returns after game exited - cpuThread = NULL; + cpuThread.join(); } VolumeHandler::EjectVolume(); @@ -517,7 +512,6 @@ THREAD_RETURN EmuThread(void *pArg) #ifdef __APPLE__ [pool release]; #endif - return 0; } // Set or get the running state diff --git a/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp b/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp index 40a7bec838..a6d5df1d47 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp @@ -19,45 +19,41 @@ #include "EXI_DeviceGecko.h" #include "../Core.h" -THREAD_RETURN ClientThreadFunc(void *arg) +void ClientThreadFunc(GeckoSockServer *arg) { - ((GeckoSockServer*)arg)->ClientThread(); - return 0; + arg->ClientThread(); } u16 GeckoSockServer::server_port; int GeckoSockServer::client_count; -Common::Thread *GeckoSockServer::connectionThread = NULL; +std::thread GeckoSockServer::connectionThread; volatile bool GeckoSockServer::server_running; std::queue GeckoSockServer::waiting_socks; Common::CriticalSection GeckoSockServer::connection_lock; GeckoSockServer::GeckoSockServer() - : clientThread(NULL) - , client_running(false) + : client_running(false) { - if (!connectionThread) - connectionThread = new Common::Thread(&GeckoConnectionWaiter, (void*)0); + if (!connectionThread.joinable()) + connectionThread = std::thread(GeckoConnectionWaiter); } GeckoSockServer::~GeckoSockServer() { - if (clientThread) + if (clientThread.joinable()) --client_count; client_running = false; - delete clientThread; - clientThread = NULL; + clientThread.join(); if (client_count <= 0) { server_running = false; - delete connectionThread; - connectionThread = NULL; + connectionThread.join(); } } -THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*) +void GeckoSockServer::GeckoConnectionWaiter() { Common::SetCurrentThreadName("Gecko Connection Waiter"); @@ -70,7 +66,7 @@ THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*) } if (!server_running) - return 0; + return; Core::DisplayMessage( StringFromFormat("USBGecko: Listening on TCP port %u", server_port), @@ -90,7 +86,6 @@ THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*) SLEEP(1); } server.Close(); - return 0; } bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) @@ -101,15 +96,15 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) if (waiting_socks.size()) { sock_to_fill = waiting_socks.front(); - if (clientThread) + if (clientThread.joinable()) { client_running = false; - delete clientThread; - clientThread = NULL; + clientThread.join(); + recv_fifo = std::queue(); send_fifo = std::queue(); } - clientThread = new Common::Thread(ClientThreadFunc, this); + clientThread = std::thread(ClientThreadFunc, this); client_count++; waiting_socks.pop(); sock_filled = true; diff --git a/Source/Core/Core/Src/HW/EXI_DeviceGecko.h b/Source/Core/Core/Src/HW/EXI_DeviceGecko.h index 7c62fc1dfa..af4642b83d 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceGecko.h +++ b/Source/Core/Core/Src/HW/EXI_DeviceGecko.h @@ -33,7 +33,7 @@ public: // Client for this server object sf::SocketTCP client; void ClientThread(); - Common::Thread *clientThread; + std::thread clientThread; Common::CriticalSection transfer_lock; std::queue send_fifo; @@ -44,11 +44,11 @@ private: volatile bool client_running; // Only ever one server thread - static THREAD_RETURN GeckoConnectionWaiter(void*); + static void GeckoConnectionWaiter(); static u16 server_port; static volatile bool server_running; - static Common::Thread *connectionThread; + static std::thread connectionThread; static std::queue waiting_socks; static Common::CriticalSection connection_lock; }; diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp index 967b11a8cf..bcb3c5d59a 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp @@ -46,8 +46,7 @@ void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate) CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename, int _card_index) : m_strFilename(_rFilename), card_index(_card_index), - m_bDirty(false), - flushThread(NULL) + m_bDirty(false) { cards[_card_index] = this; et_this_card = CoreTiming::RegisterEvent(_rName.c_str(), FlushCallback); @@ -103,9 +102,8 @@ CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rF } } -THREAD_RETURN innerFlush(void *pArgs) +void innerFlush(flushStruct* data) { - flushStruct *data = ((flushStruct *)pArgs); FILE* pFile = NULL; pFile = fopen(data->filename.c_str(), "wb"); @@ -123,7 +121,7 @@ THREAD_RETURN innerFlush(void *pArgs) PanicAlertT("Could not write memory card file %s.\n\n" "Are you running Dolphin from a CD/DVD, or is the save file maybe write protected?", data->filename.c_str()); delete data; - return 0; + return; } fwrite(data->memcardContent, data->memcardSize, 1, pFile); @@ -134,7 +132,7 @@ THREAD_RETURN innerFlush(void *pArgs) data->filename.c_str()).c_str(), 4000); delete data; - return 0; + return; } // Flush memory card contents to disc @@ -143,10 +141,9 @@ void CEXIMemoryCard::Flush(bool exiting) if(!m_bDirty) return; - if(flushThread) + if (flushThread.joinable()) { - delete flushThread; - flushThread = NULL; + flushThread.join(); } if(!exiting) @@ -159,9 +156,9 @@ void CEXIMemoryCard::Flush(bool exiting) fs->memcardSize = memory_card_size; fs->bExiting = exiting; - flushThread = new Common::Thread(innerFlush, fs); - if(exiting) - flushThread->WaitForDeath(); + flushThread = std::thread(innerFlush, fs); + if (exiting) + flushThread.join(); m_bDirty = false; } @@ -171,10 +168,10 @@ CEXIMemoryCard::~CEXIMemoryCard() Flush(true); delete[] memory_card_content; memory_card_content = NULL; - if(flushThread) + + if (flushThread.joinable()) { - delete flushThread; - flushThread = NULL; + flushThread.join(); } } @@ -186,10 +183,9 @@ bool CEXIMemoryCard::IsPresent() void CEXIMemoryCard::SetCS(int cs) { // So that memory card won't be invalidated during flushing - if(flushThread) + if (flushThread.joinable()) { - delete flushThread; - flushThread = NULL; + flushThread.join(); } if (cs) // not-selected to selected diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h index 2acc4d7577..127dfa2b15 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h +++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h @@ -90,7 +90,7 @@ private: int memory_card_size; //! in bytes, must be power of 2. u8 *memory_card_content; - Common::Thread *flushThread; + std::thread flushThread; protected: virtual void TransferByte(u8 &byte); diff --git a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp index 999a861c22..1940be4bdb 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp +++ b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp @@ -22,14 +22,14 @@ #include "Thread.h" #include -static Common::Thread *connectionThread = NULL; +static std::thread connectionThread; static std::queue waiting_socks; static Common::CriticalSection cs_gba; namespace { volatile bool server_running; } // --- GameBoy Advance "Link Cable" --- -THREAD_RETURN GBAConnectionWaiter(void*) +void GBAConnectionWaiter() { server_running = true; @@ -38,7 +38,7 @@ THREAD_RETURN GBAConnectionWaiter(void*) sf::SocketTCP server; // "dolphin gba" if (!server.Listen(0xd6ba)) - return 0; + return; server.SetBlocking(false); @@ -54,14 +54,14 @@ THREAD_RETURN GBAConnectionWaiter(void*) SLEEP(1); } server.Close(); - return 0; + return; } void GBAConnectionWaiter_Shutdown() { server_running = false; - delete connectionThread; - connectionThread = NULL; + if (connectionThread.joinable()) + connectionThread.join(); } bool GetAvailableSock(sf::SocketTCP& sock_to_fill) @@ -82,8 +82,8 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill) GBASockServer::GBASockServer() { - if (!connectionThread) - connectionThread = new Common::Thread(GBAConnectionWaiter, (void*)0); + if (!connectionThread.joinable()) + connectionThread = std::thread(GBAConnectionWaiter); } GBASockServer::~GBASockServer() diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index f167a741f2..53cc8019ab 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -41,10 +41,10 @@ bool g_real_wiimotes_initialized = false; unsigned int g_wiimotes_found = 0; volatile bool g_run_wiimote_thread = false; -Common::Thread *g_wiimote_threads[MAX_WIIMOTES] = {}; +std::thread g_wiimote_threads[MAX_WIIMOTES] = {}; Common::CriticalSection g_refresh_critsec; -THREAD_RETURN WiimoteThreadFunc(void* arg); +void WiimoteThreadFunc(Wiimote& arg); void StartWiimoteThreads(); void StopWiimoteThreads(); @@ -433,10 +433,10 @@ void Refresh() if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) || !g_wiimotes[i]->IsConnected())) { + // TODO: this looks broken delete g_wiimotes[i]; g_wiimotes[i] = NULL; - delete g_wiimote_threads[i]; - g_wiimote_threads[i] = NULL; + g_wiimote_threads[i].join(); --g_wiimotes_found; } @@ -510,57 +510,51 @@ void StartWiimoteThreads() { g_run_wiimote_thread = true; for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (g_wiimotes[i] && !g_wiimote_threads[i]) - g_wiimote_threads[i] = new Common::Thread(WiimoteThreadFunc, g_wiimotes[i]); + if (g_wiimotes[i]) + g_wiimote_threads[i] = std::thread(WiimoteThreadFunc, *g_wiimotes[i]); } void StopWiimoteThreads() { g_run_wiimote_thread = false; for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (g_wiimote_threads[i]) - { - delete g_wiimote_threads[i]; - g_wiimote_threads[i] = NULL; - } + if (g_wiimote_threads[i].joinable()) + g_wiimote_threads[i].join(); } -THREAD_RETURN WiimoteThreadFunc(void* arg) +void WiimoteThreadFunc(Wiimote& wiimote) { #ifdef __APPLE__ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; #endif - Wiimote* const wiimote = (Wiimote*)arg; - char thname[] = "Wiimote # Thread"; - thname[8] = (char)('1' + wiimote->index); + thname[8] = (char)('1' + wiimote.index); Common::SetCurrentThreadName(thname); // rumble briefly - wiimote->Rumble(); + wiimote.Rumble(); - Host_ConnectWiimote(wiimote->index, true); + Host_ConnectWiimote(wiimote.index, true); // main loop - while (g_run_wiimote_thread && wiimote->IsConnected()) + while (g_run_wiimote_thread && wiimote.IsConnected()) { // hopefully this is alright - while (wiimote->Write()) {} + while (wiimote.Write()) {} #ifndef __APPLE__ // sleep if there was nothing to read - if (false == wiimote->Read()) + if (false == wiimote.Read()) #endif Common::SleepCurrentThread(1); } - Host_ConnectWiimote(wiimote->index, false); + Host_ConnectWiimote(wiimote.index, false); #ifdef __APPLE__ [pool release]; #endif - return 0; } }; // end of namespace diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 2f68db0feb..85f27e19cf 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -69,7 +69,7 @@ static u8 *undoLoad = NULL; static bool const bCompressed = true; -static Common::Thread *saveThread = NULL; +static std::thread saveThread; // Don't forget to increase this after doing changes on the savestate system @@ -159,9 +159,8 @@ void VerifyBufferStateCallback(u64 userdata, int cyclesLate) state_op_in_progress = false; } -THREAD_RETURN CompressAndDumpState(void *pArgs) +void CompressAndDumpState(saveStruct* saveArg) { - saveStruct *saveArg = (saveStruct *)pArgs; u8 *buffer = saveArg->buffer; size_t sz = saveArg->size; lzo_uint out_len = 0; @@ -185,7 +184,7 @@ THREAD_RETURN CompressAndDumpState(void *pArgs) { Core::DisplayMessage("Could not save state", 2000); delete[] buffer; - return 0; + return; } // Setting up the header @@ -229,7 +228,6 @@ THREAD_RETURN CompressAndDumpState(void *pArgs) filename.c_str()).c_str(), 2000); state_op_in_progress = false; - return 0; } void SaveStateCallback(u64 userdata, int cyclesLate) @@ -263,7 +261,7 @@ void SaveStateCallback(u64 userdata, int cyclesLate) Core::DisplayMessage("Saving State...", 1000); - saveThread = new Common::Thread(CompressAndDumpState, saveData); + saveThread = std::thread(CompressAndDumpState, saveData); // Resume the clock PowerPC::Start(); @@ -592,10 +590,9 @@ void State_VerifyBuffer(u8 **buffer) void State_Flush() { // If already saving state, wait for it to finish - if (saveThread) + if (saveThread.joinable()) { - delete saveThread; - saveThread = NULL; + saveThread.join(); } } diff --git a/Source/Core/DolphinWX/Src/NetPlay.cpp b/Source/Core/DolphinWX/Src/NetPlay.cpp index 62b00c9439..179ea3e3a1 100644 --- a/Source/Core/DolphinWX/Src/NetPlay.cpp +++ b/Source/Core/DolphinWX/Src/NetPlay.cpp @@ -38,10 +38,9 @@ extern CFrame* main_frame; DEFINE_EVENT_TYPE(wxEVT_THREAD) -THREAD_RETURN NetPlayThreadFunc(void* arg) +void NetPlayThreadFunc(NetPlay* np) { - ((NetPlay*)arg)->Entry(); - return 0; + np->Entry(); } // called from ---GUI--- thread diff --git a/Source/Core/DolphinWX/Src/NetPlay.h b/Source/Core/DolphinWX/Src/NetPlay.h index cdc6305c67..dcdd8bdd2e 100644 --- a/Source/Core/DolphinWX/Src/NetPlay.h +++ b/Source/Core/DolphinWX/Src/NetPlay.h @@ -76,8 +76,6 @@ enum CON_ERR_VERSION_MISMATCH }; -THREAD_RETURN NetPlayThreadFunc(void* arg); - // something like this should be in Common stuff class CritLocker { @@ -116,7 +114,6 @@ public: u8 GetPadNum(u8 numPAD); protected: - //NetPlay(Common::ThreadFunc entry, void* arg) : m_thread(entry, arg) {} //void GetBufferedPad(const u8 pad_nb, NetPad* const netvalues); void ClearBuffers(); void UpdateGUI(); @@ -149,7 +146,7 @@ protected: NetPlayDiag* m_dialog; sf::SocketTCP m_socket; - Common::Thread* m_thread; + std::thread m_thread; sf::Selector m_selector; std::string m_selected_game; @@ -166,6 +163,8 @@ private: }; +void NetPlayThreadFunc(NetPlay* arg); + void NetPlay_Enable(NetPlay* const np); void NetPlay_Disable(); diff --git a/Source/Core/DolphinWX/Src/NetPlayClient.cpp b/Source/Core/DolphinWX/Src/NetPlayClient.cpp index a685d1ee4f..639dee80ef 100644 --- a/Source/Core/DolphinWX/Src/NetPlayClient.cpp +++ b/Source/Core/DolphinWX/Src/NetPlayClient.cpp @@ -7,8 +7,7 @@ NetPlayClient::~NetPlayClient() if (is_connected) { m_do_loop = false; - m_thread->WaitForDeath(); - delete m_thread; + m_thread.join(); } } @@ -73,7 +72,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, const s is_connected = true; m_selector.Add(m_socket); - m_thread = new Common::Thread(NetPlayThreadFunc, this); + m_thread = std::thread(NetPlayThreadFunc, this); } } else diff --git a/Source/Core/DolphinWX/Src/NetPlayServer.cpp b/Source/Core/DolphinWX/Src/NetPlayServer.cpp index 70992630e7..f6c6de5de9 100644 --- a/Source/Core/DolphinWX/Src/NetPlayServer.cpp +++ b/Source/Core/DolphinWX/Src/NetPlayServer.cpp @@ -7,8 +7,7 @@ NetPlayServer::~NetPlayServer() if (is_connected) { m_do_loop = false; - m_thread->WaitForDeath(); - delete m_thread; + m_thread.join(); } } @@ -41,7 +40,7 @@ NetPlayServer::NetPlayServer(const u16 port, const std::string& name, NetPlayDia is_connected = true; m_selector.Add(m_socket); - m_thread = new Common::Thread(NetPlayThreadFunc, this); + m_thread = std::thread(NetPlayThreadFunc, this); } else is_connected = false; diff --git a/Source/Core/InputCommon/Src/UDPWiimote.cpp b/Source/Core/InputCommon/Src/UDPWiimote.cpp index 6fde1732d9..558e4d902d 100644 --- a/Source/Core/InputCommon/Src/UDPWiimote.cpp +++ b/Source/Core/InputCommon/Src/UDPWiimote.cpp @@ -47,7 +47,7 @@ struct UDPWiimote::_d { - Common::Thread * thread; + std::thread thread; std::list sockfds; Common::CriticalSection termLock,mutex,nameMutex; volatile bool exit; @@ -56,15 +56,9 @@ struct UDPWiimote::_d int UDPWiimote::noinst=0; -void _UDPWiiThread(void* arg) +void UDPWiiThread(UDPWiimote* arg) { - ((UDPWiimote*)arg)->mainThread(); -} - -THREAD_RETURN UDPWiiThread(void* arg) -{ - _UDPWiiThread(arg); - return 0; + arg->mainThread(); } UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) : @@ -86,7 +80,6 @@ UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) : #endif struct addrinfo hints, *servinfo, *p; int rv; - d->thread=NULL; #ifdef _WIN32 if (noinst==0) @@ -142,7 +135,7 @@ UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) : initBroadcastIPv4(); initBroadcastIPv6(); d->termLock.Enter(); - d->thread = new Common::Thread(UDPWiiThread,this); + d->thread = std::thread(UDPWiiThread, this); d->termLock.Leave(); return; } @@ -226,8 +219,8 @@ void UDPWiimote::mainThread() UDPWiimote::~UDPWiimote() { - d->exit=true; - d->thread->WaitForDeath(); + d->exit = true; + d->thread.join(); d->termLock.Enter(); d->termLock.Leave(); for (std::list::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) diff --git a/Source/Core/InputCommon/Src/UDPWiimote.h b/Source/Core/InputCommon/Src/UDPWiimote.h index c1c39b2887..02fa4f66bc 100644 --- a/Source/Core/InputCommon/Src/UDPWiimote.h +++ b/Source/Core/InputCommon/Src/UDPWiimote.h @@ -21,6 +21,7 @@ class UDPWiimote { + friend void UDPWiiThread(UDPWiimote* arg); public: UDPWiimote(const char * port, const char * name, int index); virtual ~UDPWiimote(); @@ -49,7 +50,6 @@ private: int index; int int_port; static int noinst; - friend void _UDPWiiThread(void* arg); void broadcastPresence(); void broadcastIPv4(const void * data, size_t size); void broadcastIPv6(const void * data, size_t size); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index 60e4286bfb..fe218070bd 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -46,7 +46,7 @@ DSPConfigDialogLLE* m_ConfigFrame = NULL; PLUGIN_GLOBALS* globals = NULL; DSPInitialize g_dspInitialize; -Common::Thread *g_hDSPThread = NULL; +std::thread g_hDSPThread; SoundStream *soundStream = NULL; bool g_InitMixer = false; @@ -211,7 +211,7 @@ void *DllDebugger(void *_hParent, bool Show) // Regular thread -THREAD_RETURN dsp_thread(void* lpParameter) +void dsp_thread() { while (bIsRunning) { @@ -226,7 +226,6 @@ THREAD_RETURN dsp_thread(void* lpParameter) } // yield? } - return 0; } void DSP_DebugBreak() @@ -276,7 +275,7 @@ void Initialize(void *init) if (g_dspInitialize.bOnThread) { - g_hDSPThread = new Common::Thread(dsp_thread, NULL); + g_hDSPThread = std::thread(dsp_thread); } #if defined(HAVE_WX) && HAVE_WX @@ -291,8 +290,7 @@ void DSP_StopSoundStream() bIsRunning = false; if (g_dspInitialize.bOnThread) { - delete g_hDSPThread; - g_hDSPThread = NULL; + g_hDSPThread.join(); } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 8822883ba0..514b7c7ff0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -108,7 +108,7 @@ void UpdateFPSDisplay(const char *text) } #if defined(HAVE_X11) && HAVE_X11 -THREAD_RETURN XEventThread(void *pArg); +void XEventThread(); void CreateXWindow (void) { @@ -137,7 +137,7 @@ void CreateXWindow (void) XMapRaised(GLWin.evdpy, GLWin.win); XSync(GLWin.evdpy, True); - GLWin.xEventThread = new Common::Thread(XEventThread, NULL); + GLWin.xEventThread = std::thread(XEventThread); } void DestroyXWindow(void) @@ -150,7 +150,7 @@ void DestroyXWindow(void) XFreeColormap(GLWin.evdpy, GLWin.attr.colormap); } -THREAD_RETURN XEventThread(void *pArg) +void XEventThread() { // Free look variables static bool mouseLookEnabled = false; @@ -305,7 +305,6 @@ THREAD_RETURN XEventThread(void *pArg) } Common::SleepCurrentThread(20); } - return 0; } #endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h index fbf9acff4d..ecb4123924 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h @@ -72,7 +72,7 @@ typedef struct { XVisualInfo *vi; GLXContext ctx; XSetWindowAttributes attr; - Common::Thread *xEventThread; + std::thread xEventThread; int x, y; unsigned int width, height; #endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index a56bdbbf9b..0c7ea23125 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -98,7 +98,7 @@ static bool s_bHaveCoverageMSAA = false; static u32 s_blendMode; #if defined(HAVE_WX) && HAVE_WX -static Common::Thread *scrshotThread = 0; +static std::thread scrshotThread; #endif #ifdef _WIN32 @@ -490,8 +490,8 @@ Renderer::~Renderer() #endif #if defined(HAVE_WX) && HAVE_WX - if (scrshotThread) - delete scrshotThread; + if (scrshotThread.joinable()) + scrshotThread.join(); #endif delete g_framebuffer_manager; @@ -1496,10 +1496,8 @@ void Renderer::FlipImageData(u8 *data, int w, int h) } #if defined(HAVE_WX) && HAVE_WX -THREAD_RETURN TakeScreenshot(void *pArgs) +void TakeScreenshot(ScrStrct* threadStruct) { - ScrStrct *threadStruct = (ScrStrct *)pArgs; - // These will contain the final image size float FloatW = (float)threadStruct->W; float FloatH = (float)threadStruct->H; @@ -1538,8 +1536,6 @@ THREAD_RETURN TakeScreenshot(void *pArgs) OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, threadStruct->filename.c_str()).c_str(), 2000); delete threadStruct; - - return 0; } #endif @@ -1569,20 +1565,17 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // Create wxImage wxImage *a = new wxImage(W, H, data); - if (scrshotThread) - { - delete scrshotThread; - scrshotThread = NULL; - } + if (scrshotThread.joinable()) + scrshotThread.join(); ScrStrct *threadStruct = new ScrStrct; threadStruct->filename = filename; threadStruct->img = a; threadStruct->H = H; threadStruct->W = W; - scrshotThread = new Common::Thread(TakeScreenshot, threadStruct); + scrshotThread = std::thread(TakeScreenshot, threadStruct); #ifdef _WIN32 - scrshotThread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); + SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); #endif bool result = true;