Replaced Common::Thread with a partial implementation of std::thread. (rvalue references are used if available, <thread> 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
This commit is contained in:
Jordan Woyak 2011-01-27 20:47:58 +00:00
parent 0371f15c23
commit 2c05c49a04
29 changed files with 484 additions and 396 deletions

View File

@ -54,10 +54,9 @@ void AOSound::SoundLoop()
} }
} }
void *soundThread(void *args) void soundThread(AOSound *aosound)
{ {
((AOSound *)args)->SoundLoop(); aosound->SoundLoop();
return NULL;
} }
bool AOSound::Start() bool AOSound::Start()
@ -66,7 +65,7 @@ bool AOSound::Start()
soundSyncEvent.Init(); soundSyncEvent.Init();
thread = new Common::Thread(soundThread, (void *)this); thread = std::thread(soundThread, this);
return true; return true;
} }
@ -81,8 +80,7 @@ void AOSound::Stop()
soundSyncEvent.Set(); soundSyncEvent.Set();
soundCriticalSection.Enter(); soundCriticalSection.Enter();
delete thread; thread.join();
thread = NULL;
if (device) if (device)
ao_close(device); ao_close(device);

View File

@ -29,7 +29,7 @@
class AOSound : public SoundStream class AOSound : public SoundStream
{ {
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
Common::Thread *thread; std::thread thread;
Common::CriticalSection soundCriticalSection; Common::CriticalSection soundCriticalSection;
Common::Event soundSyncEvent; Common::Event soundSyncEvent;

View File

@ -91,10 +91,9 @@ bool DSound::WriteDataToBuffer(DWORD dwOffset, // Our own write
} }
// The audio thread. // The audio thread.
THREAD_RETURN soundThread(void* args) void soundThread(DSound* dsound)
{ {
(reinterpret_cast<DSound *>(args))->SoundLoop(); dsound->SoundLoop();
return 0;
} }
void DSound::SoundLoop() void DSound::SoundLoop()
@ -138,7 +137,7 @@ bool DSound::Start()
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1); memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0); dsBuffer->Unlock(p1, num1, 0, 0);
thread = new Common::Thread(soundThread, (void *)this); thread = std::thread(soundThread, this);
return true; return true;
} }
@ -179,8 +178,7 @@ void DSound::Stop()
// kick the thread if it's waiting // kick the thread if it's waiting
soundSyncEvent.Set(); soundSyncEvent.Set();
delete thread; thread.join();
thread = NULL;
dsBuffer->Stop(); dsBuffer->Stop();
dsBuffer->Release(); dsBuffer->Release();
ds->Release(); ds->Release();

View File

@ -31,7 +31,7 @@
class DSound : public SoundStream class DSound : public SoundStream
{ {
#ifdef _WIN32 #ifdef _WIN32
Common::Thread *thread; std::thread thread;
Common::EventEx soundSyncEvent; Common::EventEx soundSyncEvent;
void *hWnd; void *hWnd;

View File

@ -44,8 +44,7 @@ bool OpenALStream::Start()
if (pContext) if (pContext)
{ {
alcMakeContextCurrent(pContext); alcMakeContextCurrent(pContext);
thread = new Common::Thread( thread = std::thread(OpenALStream::ThreadFunc, this);
OpenALStream::ThreadFunc, (void *)this);
bReturn = true; bReturn = true;
} }
else else
@ -75,8 +74,7 @@ void OpenALStream::Stop()
// kick the thread if it's waiting // kick the thread if it's waiting
soundSyncEvent.Set(); soundSyncEvent.Set();
delete thread; thread.join();
thread = NULL;
alSourceStop(uiSource); alSourceStop(uiSource);
alSourcei(uiSource, AL_BUFFER, 0); 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<OpenALStream *>(args))->SoundLoop(); alstream->SoundLoop();
return 0;
} }
void OpenALStream::SoundLoop() void OpenALStream::SoundLoop()

View File

@ -58,10 +58,10 @@ public:
virtual bool usesMixer() const { return true; } virtual bool usesMixer() const { return true; }
virtual void Update(); virtual void Update();
static THREAD_RETURN ThreadFunc(void* args); static void ThreadFunc(OpenALStream* args);
private: private:
Common::Thread *thread; std::thread thread;
Common::EventEx soundSyncEvent; Common::EventEx soundSyncEvent;
short realtimeBuffer[OAL_MAX_SAMPLES * 2]; short realtimeBuffer[OAL_MAX_SAMPLES * 2];

View File

@ -845,6 +845,10 @@
RelativePath=".\Src\stdafx.h" RelativePath=".\Src\stdafx.h"
> >
</File> </File>
<File
RelativePath=".\Src\StdThread.h"
>
</File>
<File <File
RelativePath=".\Src\StringUtil.cpp" RelativePath=".\Src\StringUtil.cpp"
> >

View File

@ -322,6 +322,7 @@
<ClInclude Include="Src\SDCardUtil.h" /> <ClInclude Include="Src\SDCardUtil.h" />
<ClInclude Include="Src\Setup.h" /> <ClInclude Include="Src\Setup.h" />
<ClInclude Include="Src\stdafx.h" /> <ClInclude Include="Src\stdafx.h" />
<ClInclude Include="Src\StdThread.h" />
<ClInclude Include="Src\StringUtil.h" /> <ClInclude Include="Src\StringUtil.h" />
<ClInclude Include="Src\svnrev.h" /> <ClInclude Include="Src\svnrev.h" />
<ClInclude Include="Src\svnrev_template.h" /> <ClInclude Include="Src\svnrev_template.h" />

View File

@ -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 <thread>
#include <thread>
#else
// partial std::thread implementation for win32/pthread
#include <algorithm>
#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 <Windows.h>
#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 <process.h>
#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 <unistd.h>
#ifndef _POSIX_THREADS
#error unsupported platform (no pthreads?)
#endif
#include <pthread.h>
#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 <typename C, typename... A>
//thread(C&& func, A&&... args);
template <typename C>
thread(C func)
{
StartThread(new Func<C>(func));
}
template <typename C, typename A>
thread(C func, A arg)
{
StartThread(new FuncArg<C, A>(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<thread&>(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<thread&>(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<unsigned>(sysinfo.dwNumberOfProcessors);
#else
return 0;
#endif
}
private:
id m_id;
#ifdef _WIN32
native_handle_type m_handle;
#endif
template <typename F>
void StartThread(F* param)
{
#ifdef USE_BEGINTHREADEX
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
#elif defined(_WIN32)
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, 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<F>, param))
m_id = id();
#endif
}
template <typename C>
class Func
{
public:
Func(C _func) : func(_func) {}
void Run() { func(); }
private:
C const func;
};
template <typename C, typename A>
class FuncArg
{
public:
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
void Run() { func(arg); }
private:
C const func;
A arg;
};
template <typename F>
static THREAD_RETURN RunAndDelete(void* param)
{
static_cast<F*>(param)->Run();
delete static_cast<F*>(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

View File

@ -26,17 +26,27 @@
namespace Common namespace Common
{ {
int Thread::CurrentId() int CurrentThreadId()
{ {
#ifdef _WIN32 #ifdef _WIN32
return GetCurrentThreadId(); return GetCurrentThreadId();
#else #else
return 0; return 0;
#endif #endif
} }
#ifdef _WIN32 #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) CriticalSection::CriticalSection(int spincount)
{ {
if (spincount) if (spincount)
@ -70,54 +80,6 @@ namespace Common
LeaveCriticalSection(&section); LeaveCriticalSection(&section);
} }
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() EventEx::EventEx()
{ {
InterlockedExchange(&m_Lock, 1); InterlockedExchange(&m_Lock, 1);
@ -301,6 +263,31 @@ namespace Common
#else // !WIN32, so must be POSIX threads #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_key_t threadname_key;
static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT; static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT;
@ -345,82 +332,6 @@ namespace Common
#endif #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) void SleepCurrentThread(int ms)
{ {
usleep(1000 * ms); usleep(1000 * ms);

View File

@ -18,37 +18,7 @@
#ifndef _THREAD_H_ #ifndef _THREAD_H_
#define _THREAD_H_ #define _THREAD_H_
#ifdef _WIN32 #include "StdThread.h"
#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 <windows.h>
#ifdef USE_BEGINTHREADEX
#define THREAD_RETURN unsigned __stdcall
#else
#define THREAD_RETURN DWORD WINAPI
#endif
#else
#include <xmmintrin.h>
#define THREAD_RETURN void*
#include <unistd.h>
#ifdef _POSIX_THREADS
#include <pthread.h>
#elif GEKKO
#include <ogc/lwp_threads.h>
#else
#error unsupported platform (no pthreads?)
#endif
#endif
// Don't include common.h here as it will break LogManager // Don't include common.h here as it will break LogManager
#include "CommonTypes.h" #include "CommonTypes.h"
@ -61,6 +31,8 @@
#define INFINITE 0xffffffff #define INFINITE 0xffffffff
#endif #endif
#include <xmmintrin.h>
//for gettimeofday and struct time(spec|val) //for gettimeofday and struct time(spec|val)
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
@ -70,6 +42,11 @@
namespace Common namespace Common
{ {
int CurrentThreadId();
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
void SetCurrentThreadAffinity(u32 mask);
class CriticalSection class CriticalSection
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -88,57 +65,6 @@ namespace Common
void Leave(); 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 #ifdef _WIN32
// Event(WaitForSingleObject) is too expensive // Event(WaitForSingleObject) is too expensive
// as it always enters Ring0 regardless of the state of lock // as it always enters Ring0 regardless of the state of lock

View File

@ -95,7 +95,7 @@ TPeekMessages Callback_PeekMessages = NULL;
TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL; TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
// Function declarations // Function declarations
THREAD_RETURN EmuThread(void *pArg); void EmuThread();
void Stop(); void Stop();
@ -104,9 +104,9 @@ bool g_bHwInit = false;
bool g_bRealWiimote = false; bool g_bRealWiimote = false;
void *g_pWindowHandle = NULL; 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; SCoreStartupParameter g_CoreStartupParameter;
@ -122,7 +122,7 @@ Common::Event cpuRunloopQuit;
std::string StopMessage(bool bMainThread, std::string Message) std::string StopMessage(bool bMainThread, std::string Message)
{ {
return StringFromFormat("Stop [%s %i]\t%s\t%s", 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() 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 // This is called from the GUI thread. See the booting call schedule in
// BootManager.cpp // BootManager.cpp
bool Init() bool Init()
{ {
if (g_EmuThread != NULL) if (g_EmuThread.joinable())
{ {
PanicAlertT("Emu Thread already running"); PanicAlertT("Emu Thread already running");
return false; return false;
@ -195,7 +195,7 @@ bool Init()
emuThreadGoing.Init(); emuThreadGoing.Init();
// Start the emu thread // Start the emu thread
g_EmuThread = new Common::Thread(EmuThread, NULL); g_EmuThread = std::thread(EmuThread);
// Wait until the emu thread is running // Wait until the emu thread is running
emuThreadGoing.MsgWait(); emuThreadGoing.MsgWait();
@ -242,14 +242,12 @@ void Stop() // - Hammertime!
Host_SetWaitCursor(false); Host_SetWaitCursor(false);
WARN_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); WARN_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str());
g_EmuThread->WaitForDeath(); g_EmuThread.join(); // Wait for emuthread to close.
delete g_EmuThread; // Wait for emuthread to close.
g_EmuThread = 0;
} }
// Create the CPU thread. which would be a CPU + Video thread in Single Core mode. // Create the CPU thread. which would be a CPU + Video thread in Single Core mode.
THREAD_RETURN CpuThread(void *pArg) void CpuThread()
{ {
#ifdef __APPLE__ #ifdef __APPLE__
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@ -269,7 +267,7 @@ THREAD_RETURN CpuThread(void *pArg)
} }
if (_CoreParameter.bLockThreads) if (_CoreParameter.bLockThreads)
Common::Thread::SetCurrentThreadAffinity(1); // Force to first core Common::SetCurrentThreadAffinity(1); // Force to first core
if (_CoreParameter.bUseFastMem) if (_CoreParameter.bUseFastMem)
{ {
@ -296,13 +294,13 @@ THREAD_RETURN CpuThread(void *pArg)
#ifdef __APPLE__ #ifdef __APPLE__
[pool release]; [pool release];
#endif #endif
return 0; return;
} }
// Initalize plugins and create emulation thread // Initalize plugins and create emulation thread
// Call browser: Init():g_EmuThread(). See the BootManager.cpp file description for a complete call schedule. // 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__ #ifdef __APPLE__
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@ -319,9 +317,9 @@ THREAD_RETURN EmuThread(void *pArg)
if (_CoreParameter.bLockThreads) if (_CoreParameter.bLockThreads)
{ {
if (cpu_info.num_cores > 3) 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 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"); 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); PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
// Spawn the CPU thread // Spawn the CPU thread
_dbg_assert_(OSHLE, cpuThread == NULL); _dbg_assert_(OSHLE, !cpuThread.joinable());
// ENTER THE VIDEO THREAD LOOP // ENTER THE VIDEO THREAD LOOP
if (_CoreParameter.bCPUThread) if (_CoreParameter.bCPUThread)
{ {
@ -428,7 +426,7 @@ THREAD_RETURN EmuThread(void *pArg)
// and then takes over and becomes the video thread // and then takes over and becomes the video thread
Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
cpuThread = new Common::Thread(CpuThread, pArg); cpuThread = std::thread(CpuThread);
Common::SetCurrentThreadName("Video thread"); Common::SetCurrentThreadName("Video thread");
// Update the window again because all stuff is initialized // 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 // Without this extra thread, the video plugin window hangs in single
// core mode since noone is pumping messages. // core mode since noone is pumping messages.
cpuThread = new Common::Thread(CpuThread, pArg); cpuThread = std::thread(CpuThread);
Common::SetCurrentThreadName("Emuthread - Idle"); Common::SetCurrentThreadName("Emuthread - Idle");
// Update the window again because all stuff is initialized // 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. // At this point, the CpuThread has already returned in SC mode.
// But it may still be waiting in Dual Core mode. // But it may still be waiting in Dual Core mode.
if (cpuThread) if (cpuThread.joinable())
{ {
// There is a CPU thread - join it. // There is a CPU thread - join it.
cpuThread->WaitForDeath(); cpuThread.join();
delete cpuThread;
// Returns after game exited
cpuThread = NULL;
} }
VolumeHandler::EjectVolume(); VolumeHandler::EjectVolume();
@ -517,7 +512,6 @@ THREAD_RETURN EmuThread(void *pArg)
#ifdef __APPLE__ #ifdef __APPLE__
[pool release]; [pool release];
#endif #endif
return 0;
} }
// Set or get the running state // Set or get the running state

View File

@ -19,45 +19,41 @@
#include "EXI_DeviceGecko.h" #include "EXI_DeviceGecko.h"
#include "../Core.h" #include "../Core.h"
THREAD_RETURN ClientThreadFunc(void *arg) void ClientThreadFunc(GeckoSockServer *arg)
{ {
((GeckoSockServer*)arg)->ClientThread(); arg->ClientThread();
return 0;
} }
u16 GeckoSockServer::server_port; u16 GeckoSockServer::server_port;
int GeckoSockServer::client_count; int GeckoSockServer::client_count;
Common::Thread *GeckoSockServer::connectionThread = NULL; std::thread GeckoSockServer::connectionThread;
volatile bool GeckoSockServer::server_running; volatile bool GeckoSockServer::server_running;
std::queue<sf::SocketTCP> GeckoSockServer::waiting_socks; std::queue<sf::SocketTCP> GeckoSockServer::waiting_socks;
Common::CriticalSection GeckoSockServer::connection_lock; Common::CriticalSection GeckoSockServer::connection_lock;
GeckoSockServer::GeckoSockServer() GeckoSockServer::GeckoSockServer()
: clientThread(NULL) : client_running(false)
, client_running(false)
{ {
if (!connectionThread) if (!connectionThread.joinable())
connectionThread = new Common::Thread(&GeckoConnectionWaiter, (void*)0); connectionThread = std::thread(GeckoConnectionWaiter);
} }
GeckoSockServer::~GeckoSockServer() GeckoSockServer::~GeckoSockServer()
{ {
if (clientThread) if (clientThread.joinable())
--client_count; --client_count;
client_running = false; client_running = false;
delete clientThread; clientThread.join();
clientThread = NULL;
if (client_count <= 0) if (client_count <= 0)
{ {
server_running = false; server_running = false;
delete connectionThread; connectionThread.join();
connectionThread = NULL;
} }
} }
THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*) void GeckoSockServer::GeckoConnectionWaiter()
{ {
Common::SetCurrentThreadName("Gecko Connection Waiter"); Common::SetCurrentThreadName("Gecko Connection Waiter");
@ -70,7 +66,7 @@ THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*)
} }
if (!server_running) if (!server_running)
return 0; return;
Core::DisplayMessage( Core::DisplayMessage(
StringFromFormat("USBGecko: Listening on TCP port %u", server_port), StringFromFormat("USBGecko: Listening on TCP port %u", server_port),
@ -90,7 +86,6 @@ THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*)
SLEEP(1); SLEEP(1);
} }
server.Close(); server.Close();
return 0;
} }
bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
@ -101,15 +96,15 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
if (waiting_socks.size()) if (waiting_socks.size())
{ {
sock_to_fill = waiting_socks.front(); sock_to_fill = waiting_socks.front();
if (clientThread) if (clientThread.joinable())
{ {
client_running = false; client_running = false;
delete clientThread; clientThread.join();
clientThread = NULL;
recv_fifo = std::queue<u8>(); recv_fifo = std::queue<u8>();
send_fifo = std::queue<u8>(); send_fifo = std::queue<u8>();
} }
clientThread = new Common::Thread(ClientThreadFunc, this); clientThread = std::thread(ClientThreadFunc, this);
client_count++; client_count++;
waiting_socks.pop(); waiting_socks.pop();
sock_filled = true; sock_filled = true;

View File

@ -33,7 +33,7 @@ public:
// Client for this server object // Client for this server object
sf::SocketTCP client; sf::SocketTCP client;
void ClientThread(); void ClientThread();
Common::Thread *clientThread; std::thread clientThread;
Common::CriticalSection transfer_lock; Common::CriticalSection transfer_lock;
std::queue<u8> send_fifo; std::queue<u8> send_fifo;
@ -44,11 +44,11 @@ private:
volatile bool client_running; volatile bool client_running;
// Only ever one server thread // Only ever one server thread
static THREAD_RETURN GeckoConnectionWaiter(void*); static void GeckoConnectionWaiter();
static u16 server_port; static u16 server_port;
static volatile bool server_running; static volatile bool server_running;
static Common::Thread *connectionThread; static std::thread connectionThread;
static std::queue<sf::SocketTCP> waiting_socks; static std::queue<sf::SocketTCP> waiting_socks;
static Common::CriticalSection connection_lock; static Common::CriticalSection connection_lock;
}; };

View File

@ -46,8 +46,7 @@ void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename, int _card_index) : CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename, int _card_index) :
m_strFilename(_rFilename), m_strFilename(_rFilename),
card_index(_card_index), card_index(_card_index),
m_bDirty(false), m_bDirty(false)
flushThread(NULL)
{ {
cards[_card_index] = this; cards[_card_index] = this;
et_this_card = CoreTiming::RegisterEvent(_rName.c_str(), FlushCallback); 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; FILE* pFile = NULL;
pFile = fopen(data->filename.c_str(), "wb"); 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" 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()); "Are you running Dolphin from a CD/DVD, or is the save file maybe write protected?", data->filename.c_str());
delete data; delete data;
return 0; return;
} }
fwrite(data->memcardContent, data->memcardSize, 1, pFile); fwrite(data->memcardContent, data->memcardSize, 1, pFile);
@ -134,7 +132,7 @@ THREAD_RETURN innerFlush(void *pArgs)
data->filename.c_str()).c_str(), 4000); data->filename.c_str()).c_str(), 4000);
delete data; delete data;
return 0; return;
} }
// Flush memory card contents to disc // Flush memory card contents to disc
@ -143,10 +141,9 @@ void CEXIMemoryCard::Flush(bool exiting)
if(!m_bDirty) if(!m_bDirty)
return; return;
if(flushThread) if (flushThread.joinable())
{ {
delete flushThread; flushThread.join();
flushThread = NULL;
} }
if(!exiting) if(!exiting)
@ -159,9 +156,9 @@ void CEXIMemoryCard::Flush(bool exiting)
fs->memcardSize = memory_card_size; fs->memcardSize = memory_card_size;
fs->bExiting = exiting; fs->bExiting = exiting;
flushThread = new Common::Thread(innerFlush, fs); flushThread = std::thread(innerFlush, fs);
if(exiting) if (exiting)
flushThread->WaitForDeath(); flushThread.join();
m_bDirty = false; m_bDirty = false;
} }
@ -171,10 +168,10 @@ CEXIMemoryCard::~CEXIMemoryCard()
Flush(true); Flush(true);
delete[] memory_card_content; delete[] memory_card_content;
memory_card_content = NULL; memory_card_content = NULL;
if(flushThread)
if (flushThread.joinable())
{ {
delete flushThread; flushThread.join();
flushThread = NULL;
} }
} }
@ -186,10 +183,9 @@ bool CEXIMemoryCard::IsPresent()
void CEXIMemoryCard::SetCS(int cs) void CEXIMemoryCard::SetCS(int cs)
{ {
// So that memory card won't be invalidated during flushing // So that memory card won't be invalidated during flushing
if(flushThread) if (flushThread.joinable())
{ {
delete flushThread; flushThread.join();
flushThread = NULL;
} }
if (cs) // not-selected to selected if (cs) // not-selected to selected

View File

@ -90,7 +90,7 @@ private:
int memory_card_size; //! in bytes, must be power of 2. int memory_card_size; //! in bytes, must be power of 2.
u8 *memory_card_content; u8 *memory_card_content;
Common::Thread *flushThread; std::thread flushThread;
protected: protected:
virtual void TransferByte(u8 &byte); virtual void TransferByte(u8 &byte);

View File

@ -22,14 +22,14 @@
#include "Thread.h" #include "Thread.h"
#include <queue> #include <queue>
static Common::Thread *connectionThread = NULL; static std::thread connectionThread;
static std::queue<sf::SocketTCP> waiting_socks; static std::queue<sf::SocketTCP> waiting_socks;
static Common::CriticalSection cs_gba; static Common::CriticalSection cs_gba;
namespace { volatile bool server_running; } namespace { volatile bool server_running; }
// --- GameBoy Advance "Link Cable" --- // --- GameBoy Advance "Link Cable" ---
THREAD_RETURN GBAConnectionWaiter(void*) void GBAConnectionWaiter()
{ {
server_running = true; server_running = true;
@ -38,7 +38,7 @@ THREAD_RETURN GBAConnectionWaiter(void*)
sf::SocketTCP server; sf::SocketTCP server;
// "dolphin gba" // "dolphin gba"
if (!server.Listen(0xd6ba)) if (!server.Listen(0xd6ba))
return 0; return;
server.SetBlocking(false); server.SetBlocking(false);
@ -54,14 +54,14 @@ THREAD_RETURN GBAConnectionWaiter(void*)
SLEEP(1); SLEEP(1);
} }
server.Close(); server.Close();
return 0; return;
} }
void GBAConnectionWaiter_Shutdown() void GBAConnectionWaiter_Shutdown()
{ {
server_running = false; server_running = false;
delete connectionThread; if (connectionThread.joinable())
connectionThread = NULL; connectionThread.join();
} }
bool GetAvailableSock(sf::SocketTCP& sock_to_fill) bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
@ -82,8 +82,8 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
GBASockServer::GBASockServer() GBASockServer::GBASockServer()
{ {
if (!connectionThread) if (!connectionThread.joinable())
connectionThread = new Common::Thread(GBAConnectionWaiter, (void*)0); connectionThread = std::thread(GBAConnectionWaiter);
} }
GBASockServer::~GBASockServer() GBASockServer::~GBASockServer()

View File

@ -41,10 +41,10 @@ bool g_real_wiimotes_initialized = false;
unsigned int g_wiimotes_found = 0; unsigned int g_wiimotes_found = 0;
volatile bool g_run_wiimote_thread = false; 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; Common::CriticalSection g_refresh_critsec;
THREAD_RETURN WiimoteThreadFunc(void* arg); void WiimoteThreadFunc(Wiimote& arg);
void StartWiimoteThreads(); void StartWiimoteThreads();
void StopWiimoteThreads(); void StopWiimoteThreads();
@ -433,10 +433,10 @@ void Refresh()
if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) || if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) ||
!g_wiimotes[i]->IsConnected())) !g_wiimotes[i]->IsConnected()))
{ {
// TODO: this looks broken
delete g_wiimotes[i]; delete g_wiimotes[i];
g_wiimotes[i] = NULL; g_wiimotes[i] = NULL;
delete g_wiimote_threads[i]; g_wiimote_threads[i].join();
g_wiimote_threads[i] = NULL;
--g_wiimotes_found; --g_wiimotes_found;
} }
@ -510,57 +510,51 @@ void StartWiimoteThreads()
{ {
g_run_wiimote_thread = true; g_run_wiimote_thread = true;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
if (g_wiimotes[i] && !g_wiimote_threads[i]) if (g_wiimotes[i])
g_wiimote_threads[i] = new Common::Thread(WiimoteThreadFunc, g_wiimotes[i]); g_wiimote_threads[i] = std::thread(WiimoteThreadFunc, *g_wiimotes[i]);
} }
void StopWiimoteThreads() void StopWiimoteThreads()
{ {
g_run_wiimote_thread = false; g_run_wiimote_thread = false;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
if (g_wiimote_threads[i]) if (g_wiimote_threads[i].joinable())
{ g_wiimote_threads[i].join();
delete g_wiimote_threads[i];
g_wiimote_threads[i] = NULL;
}
} }
THREAD_RETURN WiimoteThreadFunc(void* arg) void WiimoteThreadFunc(Wiimote& wiimote)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#endif #endif
Wiimote* const wiimote = (Wiimote*)arg;
char thname[] = "Wiimote # Thread"; char thname[] = "Wiimote # Thread";
thname[8] = (char)('1' + wiimote->index); thname[8] = (char)('1' + wiimote.index);
Common::SetCurrentThreadName(thname); Common::SetCurrentThreadName(thname);
// rumble briefly // rumble briefly
wiimote->Rumble(); wiimote.Rumble();
Host_ConnectWiimote(wiimote->index, true); Host_ConnectWiimote(wiimote.index, true);
// main loop // main loop
while (g_run_wiimote_thread && wiimote->IsConnected()) while (g_run_wiimote_thread && wiimote.IsConnected())
{ {
// hopefully this is alright // hopefully this is alright
while (wiimote->Write()) {} while (wiimote.Write()) {}
#ifndef __APPLE__ #ifndef __APPLE__
// sleep if there was nothing to read // sleep if there was nothing to read
if (false == wiimote->Read()) if (false == wiimote.Read())
#endif #endif
Common::SleepCurrentThread(1); Common::SleepCurrentThread(1);
} }
Host_ConnectWiimote(wiimote->index, false); Host_ConnectWiimote(wiimote.index, false);
#ifdef __APPLE__ #ifdef __APPLE__
[pool release]; [pool release];
#endif #endif
return 0;
} }
}; // end of namespace }; // end of namespace

View File

@ -69,7 +69,7 @@ static u8 *undoLoad = NULL;
static bool const bCompressed = true; 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 // 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; state_op_in_progress = false;
} }
THREAD_RETURN CompressAndDumpState(void *pArgs) void CompressAndDumpState(saveStruct* saveArg)
{ {
saveStruct *saveArg = (saveStruct *)pArgs;
u8 *buffer = saveArg->buffer; u8 *buffer = saveArg->buffer;
size_t sz = saveArg->size; size_t sz = saveArg->size;
lzo_uint out_len = 0; lzo_uint out_len = 0;
@ -185,7 +184,7 @@ THREAD_RETURN CompressAndDumpState(void *pArgs)
{ {
Core::DisplayMessage("Could not save state", 2000); Core::DisplayMessage("Could not save state", 2000);
delete[] buffer; delete[] buffer;
return 0; return;
} }
// Setting up the header // Setting up the header
@ -229,7 +228,6 @@ THREAD_RETURN CompressAndDumpState(void *pArgs)
filename.c_str()).c_str(), 2000); filename.c_str()).c_str(), 2000);
state_op_in_progress = false; state_op_in_progress = false;
return 0;
} }
void SaveStateCallback(u64 userdata, int cyclesLate) void SaveStateCallback(u64 userdata, int cyclesLate)
@ -263,7 +261,7 @@ void SaveStateCallback(u64 userdata, int cyclesLate)
Core::DisplayMessage("Saving State...", 1000); Core::DisplayMessage("Saving State...", 1000);
saveThread = new Common::Thread(CompressAndDumpState, saveData); saveThread = std::thread(CompressAndDumpState, saveData);
// Resume the clock // Resume the clock
PowerPC::Start(); PowerPC::Start();
@ -592,10 +590,9 @@ void State_VerifyBuffer(u8 **buffer)
void State_Flush() void State_Flush()
{ {
// If already saving state, wait for it to finish // If already saving state, wait for it to finish
if (saveThread) if (saveThread.joinable())
{ {
delete saveThread; saveThread.join();
saveThread = NULL;
} }
} }

View File

@ -38,10 +38,9 @@ extern CFrame* main_frame;
DEFINE_EVENT_TYPE(wxEVT_THREAD) DEFINE_EVENT_TYPE(wxEVT_THREAD)
THREAD_RETURN NetPlayThreadFunc(void* arg) void NetPlayThreadFunc(NetPlay* np)
{ {
((NetPlay*)arg)->Entry(); np->Entry();
return 0;
} }
// called from ---GUI--- thread // called from ---GUI--- thread

View File

@ -76,8 +76,6 @@ enum
CON_ERR_VERSION_MISMATCH CON_ERR_VERSION_MISMATCH
}; };
THREAD_RETURN NetPlayThreadFunc(void* arg);
// something like this should be in Common stuff // something like this should be in Common stuff
class CritLocker class CritLocker
{ {
@ -116,7 +114,6 @@ public:
u8 GetPadNum(u8 numPAD); u8 GetPadNum(u8 numPAD);
protected: protected:
//NetPlay(Common::ThreadFunc entry, void* arg) : m_thread(entry, arg) {}
//void GetBufferedPad(const u8 pad_nb, NetPad* const netvalues); //void GetBufferedPad(const u8 pad_nb, NetPad* const netvalues);
void ClearBuffers(); void ClearBuffers();
void UpdateGUI(); void UpdateGUI();
@ -149,7 +146,7 @@ protected:
NetPlayDiag* m_dialog; NetPlayDiag* m_dialog;
sf::SocketTCP m_socket; sf::SocketTCP m_socket;
Common::Thread* m_thread; std::thread m_thread;
sf::Selector<sf::SocketTCP> m_selector; sf::Selector<sf::SocketTCP> m_selector;
std::string m_selected_game; std::string m_selected_game;
@ -166,6 +163,8 @@ private:
}; };
void NetPlayThreadFunc(NetPlay* arg);
void NetPlay_Enable(NetPlay* const np); void NetPlay_Enable(NetPlay* const np);
void NetPlay_Disable(); void NetPlay_Disable();

View File

@ -7,8 +7,7 @@ NetPlayClient::~NetPlayClient()
if (is_connected) if (is_connected)
{ {
m_do_loop = false; m_do_loop = false;
m_thread->WaitForDeath(); m_thread.join();
delete m_thread;
} }
} }
@ -73,7 +72,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, const s
is_connected = true; is_connected = true;
m_selector.Add(m_socket); m_selector.Add(m_socket);
m_thread = new Common::Thread(NetPlayThreadFunc, this); m_thread = std::thread(NetPlayThreadFunc, this);
} }
} }
else else

View File

@ -7,8 +7,7 @@ NetPlayServer::~NetPlayServer()
if (is_connected) if (is_connected)
{ {
m_do_loop = false; m_do_loop = false;
m_thread->WaitForDeath(); m_thread.join();
delete m_thread;
} }
} }
@ -41,7 +40,7 @@ NetPlayServer::NetPlayServer(const u16 port, const std::string& name, NetPlayDia
is_connected = true; is_connected = true;
m_selector.Add(m_socket); m_selector.Add(m_socket);
m_thread = new Common::Thread(NetPlayThreadFunc, this); m_thread = std::thread(NetPlayThreadFunc, this);
} }
else else
is_connected = false; is_connected = false;

View File

@ -47,7 +47,7 @@
struct UDPWiimote::_d struct UDPWiimote::_d
{ {
Common::Thread * thread; std::thread thread;
std::list<sock_t> sockfds; std::list<sock_t> sockfds;
Common::CriticalSection termLock,mutex,nameMutex; Common::CriticalSection termLock,mutex,nameMutex;
volatile bool exit; volatile bool exit;
@ -56,15 +56,9 @@ struct UDPWiimote::_d
int UDPWiimote::noinst=0; int UDPWiimote::noinst=0;
void _UDPWiiThread(void* arg) void UDPWiiThread(UDPWiimote* arg)
{ {
((UDPWiimote*)arg)->mainThread(); arg->mainThread();
}
THREAD_RETURN UDPWiiThread(void* arg)
{
_UDPWiiThread(arg);
return 0;
} }
UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) : 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 #endif
struct addrinfo hints, *servinfo, *p; struct addrinfo hints, *servinfo, *p;
int rv; int rv;
d->thread=NULL;
#ifdef _WIN32 #ifdef _WIN32
if (noinst==0) if (noinst==0)
@ -142,7 +135,7 @@ UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) :
initBroadcastIPv4(); initBroadcastIPv4();
initBroadcastIPv6(); initBroadcastIPv6();
d->termLock.Enter(); d->termLock.Enter();
d->thread = new Common::Thread(UDPWiiThread,this); d->thread = std::thread(UDPWiiThread, this);
d->termLock.Leave(); d->termLock.Leave();
return; return;
} }
@ -226,8 +219,8 @@ void UDPWiimote::mainThread()
UDPWiimote::~UDPWiimote() UDPWiimote::~UDPWiimote()
{ {
d->exit=true; d->exit = true;
d->thread->WaitForDeath(); d->thread.join();
d->termLock.Enter(); d->termLock.Enter();
d->termLock.Leave(); d->termLock.Leave();
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)

View File

@ -21,6 +21,7 @@
class UDPWiimote class UDPWiimote
{ {
friend void UDPWiiThread(UDPWiimote* arg);
public: public:
UDPWiimote(const char * port, const char * name, int index); UDPWiimote(const char * port, const char * name, int index);
virtual ~UDPWiimote(); virtual ~UDPWiimote();
@ -49,7 +50,6 @@ private:
int index; int index;
int int_port; int int_port;
static int noinst; static int noinst;
friend void _UDPWiiThread(void* arg);
void broadcastPresence(); void broadcastPresence();
void broadcastIPv4(const void * data, size_t size); void broadcastIPv4(const void * data, size_t size);
void broadcastIPv6(const void * data, size_t size); void broadcastIPv6(const void * data, size_t size);

View File

@ -46,7 +46,7 @@ DSPConfigDialogLLE* m_ConfigFrame = NULL;
PLUGIN_GLOBALS* globals = NULL; PLUGIN_GLOBALS* globals = NULL;
DSPInitialize g_dspInitialize; DSPInitialize g_dspInitialize;
Common::Thread *g_hDSPThread = NULL; std::thread g_hDSPThread;
SoundStream *soundStream = NULL; SoundStream *soundStream = NULL;
bool g_InitMixer = false; bool g_InitMixer = false;
@ -211,7 +211,7 @@ void *DllDebugger(void *_hParent, bool Show)
// Regular thread // Regular thread
THREAD_RETURN dsp_thread(void* lpParameter) void dsp_thread()
{ {
while (bIsRunning) while (bIsRunning)
{ {
@ -226,7 +226,6 @@ THREAD_RETURN dsp_thread(void* lpParameter)
} }
// yield? // yield?
} }
return 0;
} }
void DSP_DebugBreak() void DSP_DebugBreak()
@ -276,7 +275,7 @@ void Initialize(void *init)
if (g_dspInitialize.bOnThread) if (g_dspInitialize.bOnThread)
{ {
g_hDSPThread = new Common::Thread(dsp_thread, NULL); g_hDSPThread = std::thread(dsp_thread);
} }
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
@ -291,8 +290,7 @@ void DSP_StopSoundStream()
bIsRunning = false; bIsRunning = false;
if (g_dspInitialize.bOnThread) if (g_dspInitialize.bOnThread)
{ {
delete g_hDSPThread; g_hDSPThread.join();
g_hDSPThread = NULL;
} }
} }

View File

@ -108,7 +108,7 @@ void UpdateFPSDisplay(const char *text)
} }
#if defined(HAVE_X11) && HAVE_X11 #if defined(HAVE_X11) && HAVE_X11
THREAD_RETURN XEventThread(void *pArg); void XEventThread();
void CreateXWindow (void) void CreateXWindow (void)
{ {
@ -137,7 +137,7 @@ void CreateXWindow (void)
XMapRaised(GLWin.evdpy, GLWin.win); XMapRaised(GLWin.evdpy, GLWin.win);
XSync(GLWin.evdpy, True); XSync(GLWin.evdpy, True);
GLWin.xEventThread = new Common::Thread(XEventThread, NULL); GLWin.xEventThread = std::thread(XEventThread);
} }
void DestroyXWindow(void) void DestroyXWindow(void)
@ -150,7 +150,7 @@ void DestroyXWindow(void)
XFreeColormap(GLWin.evdpy, GLWin.attr.colormap); XFreeColormap(GLWin.evdpy, GLWin.attr.colormap);
} }
THREAD_RETURN XEventThread(void *pArg) void XEventThread()
{ {
// Free look variables // Free look variables
static bool mouseLookEnabled = false; static bool mouseLookEnabled = false;
@ -305,7 +305,6 @@ THREAD_RETURN XEventThread(void *pArg)
} }
Common::SleepCurrentThread(20); Common::SleepCurrentThread(20);
} }
return 0;
} }
#endif #endif

View File

@ -72,7 +72,7 @@ typedef struct {
XVisualInfo *vi; XVisualInfo *vi;
GLXContext ctx; GLXContext ctx;
XSetWindowAttributes attr; XSetWindowAttributes attr;
Common::Thread *xEventThread; std::thread xEventThread;
int x, y; int x, y;
unsigned int width, height; unsigned int width, height;
#endif #endif

View File

@ -98,7 +98,7 @@ static bool s_bHaveCoverageMSAA = false;
static u32 s_blendMode; static u32 s_blendMode;
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
static Common::Thread *scrshotThread = 0; static std::thread scrshotThread;
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -490,8 +490,8 @@ Renderer::~Renderer()
#endif #endif
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
if (scrshotThread) if (scrshotThread.joinable())
delete scrshotThread; scrshotThread.join();
#endif #endif
delete g_framebuffer_manager; delete g_framebuffer_manager;
@ -1496,10 +1496,8 @@ void Renderer::FlipImageData(u8 *data, int w, int h)
} }
#if defined(HAVE_WX) && HAVE_WX #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 // These will contain the final image size
float FloatW = (float)threadStruct->W; float FloatW = (float)threadStruct->W;
float FloatH = (float)threadStruct->H; 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, OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH,
threadStruct->filename.c_str()).c_str(), 2000); threadStruct->filename.c_str()).c_str(), 2000);
delete threadStruct; delete threadStruct;
return 0;
} }
#endif #endif
@ -1569,20 +1565,17 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
// Create wxImage // Create wxImage
wxImage *a = new wxImage(W, H, data); wxImage *a = new wxImage(W, H, data);
if (scrshotThread) if (scrshotThread.joinable())
{ scrshotThread.join();
delete scrshotThread;
scrshotThread = NULL;
}
ScrStrct *threadStruct = new ScrStrct; ScrStrct *threadStruct = new ScrStrct;
threadStruct->filename = filename; threadStruct->filename = filename;
threadStruct->img = a; threadStruct->img = a;
threadStruct->H = H; threadStruct->W = W; threadStruct->H = H; threadStruct->W = W;
scrshotThread = new Common::Thread(TakeScreenshot, threadStruct); scrshotThread = std::thread(TakeScreenshot, threadStruct);
#ifdef _WIN32 #ifdef _WIN32
scrshotThread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
#endif #endif
bool result = true; bool result = true;