Replaced Common::CriticalSection with a std::mutex implementation. 64bit Windows builds now use SRWLocks and ConditionVariables(requires Vista/7, x64 builds will no longer work on Windows XP x64). Tell me if you hate that. Removed Common::EventEx. Common::Event now uses a std::condition_variable impl.(using ConditionVariables on Windows x64, Events on x86, or posix condition variables elsewhere). I experience slight speed improvements with these changes.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7294 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Jordan Woyak 2011-03-05 06:11:26 +00:00
commit 423018f811
56 changed files with 918 additions and 835 deletions

View file

@ -47,9 +47,11 @@ void AOSound::SoundLoop()
while (!threadData) while (!threadData)
{ {
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Enter();
{
std::lock_guard<std::mutex> lk(soundCriticalSection);
ao_play(device, (char*)realtimeBuffer, numBytesToRender); ao_play(device, (char*)realtimeBuffer, numBytesToRender);
soundCriticalSection.Leave(); }
soundSyncEvent.Wait(); soundSyncEvent.Wait();
} }
@ -59,8 +61,6 @@ bool AOSound::Start()
{ {
memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); memset(realtimeBuffer, 0, sizeof(realtimeBuffer));
soundSyncEvent.Init();
thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this); thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this);
return true; return true;
} }
@ -75,7 +75,8 @@ void AOSound::Stop()
threadData = 1; threadData = 1;
soundSyncEvent.Set(); soundSyncEvent.Set();
soundCriticalSection.Enter(); {
std::lock_guard<std::mutex> lk(soundCriticalSection);
thread.join(); thread.join();
if (device) if (device)
@ -84,9 +85,7 @@ void AOSound::Stop()
ao_shutdown(); ao_shutdown();
device = NULL; device = NULL;
soundCriticalSection.Leave(); }
soundSyncEvent.Shutdown();
} }
AOSound::~AOSound() AOSound::~AOSound()

View file

@ -30,7 +30,7 @@ class AOSound : public SoundStream
{ {
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
std::thread thread; std::thread thread;
Common::CriticalSection soundCriticalSection; std::mutex soundCriticalSection;
Common::Event soundSyncEvent; Common::Event soundSyncEvent;
int buf_size; int buf_size;

View file

@ -119,8 +119,6 @@ void DSound::SoundLoop()
bool DSound::Start() bool DSound::Start()
{ {
soundSyncEvent.Init();
if (FAILED(DirectSoundCreate8(0, &ds, 0))) if (FAILED(DirectSoundCreate8(0, &ds, 0)))
return false; return false;
if (hWnd) if (hWnd)
@ -180,7 +178,5 @@ void DSound::Stop()
dsBuffer->Stop(); dsBuffer->Stop();
dsBuffer->Release(); dsBuffer->Release();
ds->Release(); ds->Release();
soundSyncEvent.Shutdown();
} }

View file

@ -32,7 +32,7 @@ class DSound : public SoundStream
{ {
#ifdef _WIN32 #ifdef _WIN32
std::thread thread; std::thread thread;
Common::EventEx soundSyncEvent; Common::Event soundSyncEvent;
void *hWnd; void *hWnd;
IDirectSound8* ds; IDirectSound8* ds;

View file

@ -32,8 +32,6 @@ bool OpenALStream::Start()
ALCdevice *pDevice = NULL; ALCdevice *pDevice = NULL;
bool bReturn = false; bool bReturn = false;
soundSyncEvent.Init();
pDeviceList = new ALDeviceList(); pDeviceList = new ALDeviceList();
if ((pDeviceList) && (pDeviceList->GetNumDevices())) if ((pDeviceList) && (pDeviceList->GetNumDevices()))
{ {
@ -92,8 +90,6 @@ void OpenALStream::Stop()
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
alcDestroyContext(pContext); alcDestroyContext(pContext);
alcCloseDevice(pDevice); alcCloseDevice(pDevice);
soundSyncEvent.Shutdown();
} }
void OpenALStream::SetVolume(int volume) void OpenALStream::SetVolume(int volume)

View file

@ -63,7 +63,7 @@ public:
private: private:
std::thread thread; std::thread thread;
Common::EventEx soundSyncEvent; Common::Event soundSyncEvent;
short realtimeBuffer[OAL_MAX_SAMPLES * 2]; short realtimeBuffer[OAL_MAX_SAMPLES * 2];
ALuint uiBuffers[OAL_NUM_BUFFERS]; ALuint uiBuffers[OAL_NUM_BUFFERS];

View file

@ -22,10 +22,10 @@ struct StreamingVoiceContext : public IXAudio2VoiceCallback
{ {
IXAudio2SourceVoice* pSourceVoice; IXAudio2SourceVoice* pSourceVoice;
CMixer *m_mixer; CMixer *m_mixer;
Common::EventEx *soundSyncEvent; Common::Event *soundSyncEvent;
short *xaBuffer; short *xaBuffer;
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent) StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event *pSyncEvent)
{ {
m_mixer = pMixer; m_mixer = pMixer;
@ -100,7 +100,6 @@ struct StreamingVoiceContext : public IXAudio2VoiceCallback
// //
if( !pSourceVoice || !context) return; if( !pSourceVoice || !context) return;
//soundSyncEvent->Init();
//soundSyncEvent->Wait(); //sync //soundSyncEvent->Wait(); //sync
//soundSyncEvent->Spin(); //or tight sync //soundSyncEvent->Spin(); //or tight sync
@ -123,8 +122,6 @@ StreamingVoiceContext* pVoiceContext = 0;
bool XAudio2::Start() bool XAudio2::Start()
{ {
//soundSyncEvent.Init();
// XAudio2 init // XAudio2 init
CoInitializeEx(NULL, COINIT_MULTITHREADED); CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr; HRESULT hr;
@ -207,5 +204,4 @@ void XAudio2::Stop()
safe_release(pXAudio2); safe_release(pXAudio2);
pMasteringVoice = NULL; pMasteringVoice = NULL;
CoUninitialize(); CoUninitialize();
//soundSyncEvent.Shutdown();
} }

View file

@ -52,7 +52,7 @@ class XAudio2 : public SoundStream
IXAudio2MasteringVoice *pMasteringVoice; IXAudio2MasteringVoice *pMasteringVoice;
IXAudio2SourceVoice *pSourceVoice; IXAudio2SourceVoice *pSourceVoice;
Common::EventEx soundSyncEvent; Common::Event soundSyncEvent;
float m_volume; float m_volume;

View file

@ -255,6 +255,8 @@
<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\StdConditionVariable.h" />
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdThread.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" />

View file

@ -121,6 +121,8 @@
<ClInclude Include="Src\Crypto\tools.h"> <ClInclude Include="Src\Crypto\tools.h">
<Filter>Crypto</Filter> <Filter>Crypto</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="CMakeLists.txt" /> <None Include="CMakeLists.txt" />

View file

@ -36,9 +36,8 @@ void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
LogManager *LogManager::m_logManager = NULL; LogManager *LogManager::m_logManager = NULL;
LogManager::LogManager() { LogManager::LogManager()
logMutex = new Common::CriticalSection(1); {
// create log files // create log files
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
@ -105,7 +104,6 @@ LogManager::~LogManager() {
delete m_fileLog; delete m_fileLog;
delete m_consoleLog; delete m_consoleLog;
delete logMutex;
} }
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
@ -127,15 +125,14 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
file, line, level_to_char[(int)level], file, line, level_to_char[(int)level],
log->getShortName(), temp); log->getShortName(), temp);
logMutex->Enter(); std::lock_guard<std::mutex> lk(logMutex);
log->trigger(level, msg); log->trigger(level, msg);
logMutex->Leave();
} }
void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener) { void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener)
logMutex->Enter(); {
std::lock_guard<std::mutex> lk(logMutex);
m_Log[type]->removeListener(listener); m_Log[type]->removeListener(listener);
logMutex->Leave();
} }
void LogManager::Init() void LogManager::Init()

View file

@ -20,6 +20,7 @@
#include "Log.h" #include "Log.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "Thread.h"
#include <vector> #include <vector>
#include <string.h> #include <string.h>
@ -102,16 +103,11 @@ private:
class ConsoleListener; class ConsoleListener;
// Avoid <windows.h> include through Thread.h
namespace Common {
class CriticalSection;
}
class LogManager : NonCopyable class LogManager : NonCopyable
{ {
private: private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
Common::CriticalSection *logMutex; std::mutex logMutex;
FileLogListener *m_fileLog; FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog; ConsoleListener *m_consoleLog;
static LogManager *m_logManager; // Singleton. Ugh. static LogManager *m_logManager; // Singleton. Ugh.

View file

@ -0,0 +1,152 @@
#ifndef CONDITION_VARIABLE_H_
#define CONDITION_VARIABLE_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 <condition_variable>
#include <condition_variable>
#else
// partial std::condition_variable implementation for win32/pthread
#include "StdMutex.h"
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
#define USE_RVALUE_REFERENCES
#endif
#if defined(_WIN32) && defined(_M_X64)
#define USE_CONDITION_VARIABLES
#elif defined(_WIN32)
#define USE_EVENTS
#endif
namespace std
{
class condition_variable
{
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
typedef CONDITION_VARIABLE native_type;
#elif defined(_WIN32)
typedef HANDLE native_type;
#else
typedef pthread_cond_t native_type;
#endif
public:
#ifdef USE_EVENTS
typedef native_type native_handle_type;
#else
typedef native_type* native_handle_type;
#endif
condition_variable()
{
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
InitializeConditionVariable(&m_handle);
#elif defined(_WIN32)
m_handle = CreateEvent(NULL, false, false, NULL);
#else
pthread_cond_init(&m_handle, NULL);
#endif
}
~condition_variable()
{
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
CloseHandle(m_handle);
#elif !defined(_WIN32)
pthread_cond_destroy(&m_handle);
#endif
}
condition_variable(const condition_variable&) /*= delete*/;
condition_variable& operator=(const condition_variable&) /*= delete*/;
void notify_one()
{
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
WakeConditionVariable(&m_handle);
#elif defined(_WIN32)
SetEvent(m_handle);
#else
pthread_cond_signal(&m_handle);
#endif
}
void notify_all()
{
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
WakeAllConditionVariable(&m_handle);
#elif defined(_WIN32)
// TODO: broken
SetEvent(m_handle);
#else
pthread_cond_broadcast(&m_handle);
#endif
}
void wait(unique_lock<mutex>& lock)
{
#ifdef _WIN32
#ifdef USE_SRWLOCKS
SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
#elif USE_CONDITION_VARIABLES
SleepConditionVariableCS(m_handle, lock.mutex()->native_handle(), INFINITE);
#else
lock.unlock();
WaitForSingleObject(m_handle, INFINITE);
lock.lock();
#endif
#else
pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
#endif
}
template <class Predicate>
void wait(unique_lock<mutex>& lock, Predicate pred)
{
while (!pred())
wait(lock);
}
//template <class Clock, class Duration>
//cv_status wait_until(unique_lock<mutex>& lock,
// const chrono::time_point<Clock, Duration>& abs_time);
//template <class Clock, class Duration, class Predicate>
// bool wait_until(unique_lock<mutex>& lock,
// const chrono::time_point<Clock, Duration>& abs_time,
// Predicate pred);
//template <class Rep, class Period>
//cv_status wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time);
//template <class Rep, class Period, class Predicate>
// bool wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time,
// Predicate pred);
native_handle_type native_handle()
{
#ifdef USE_EVENTS
return m_handle;
#else
return &m_handle;
#endif
}
private:
native_type m_handle;
};
}
#endif
#endif

View file

@ -0,0 +1,352 @@
#ifndef MUTEX_H_
#define MUTEX_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 <mutex>
#include <mutex>
#else
// partial <mutex> implementation for win32/pthread
#include <algorithm>
#if defined(_WIN32)
// WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#else
// POSIX
#include <pthread.h>
#endif
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
#define USE_RVALUE_REFERENCES
#endif
#if defined(_WIN32) && defined(_M_X64)
#define USE_SRWLOCKS
#endif
namespace std
{
class recursive_mutex
{
#ifdef _WIN32
typedef CRITICAL_SECTION native_type;
#else
typedef pthread_mutex_t native_type;
#endif
public:
typedef native_type* native_handle_type;
recursive_mutex(const recursive_mutex&) /*= delete*/;
recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
recursive_mutex()
{
#ifdef _WIN32
InitializeCriticalSection(&m_handle);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_handle, &attr);
#endif
}
~recursive_mutex()
{
#ifdef _WIN32
DeleteCriticalSection(&m_handle);
#else
pthread_mutex_destroy(&m_handle);
#endif
}
void lock()
{
#ifdef _WIN32
EnterCriticalSection(&m_handle);
#else
pthread_mutex_lock(&m_handle);
#endif
}
void unlock()
{
#ifdef _WIN32
LeaveCriticalSection(&m_handle);
#else
pthread_mutex_unlock(&m_handle);
#endif
}
bool try_lock()
{
#ifdef _WIN32
return (0 != TryEnterCriticalSection(&m_handle));
#else
return !pthread_mutex_trylock(&m_handle);
#endif
}
native_handle_type native_handle()
{
return &m_handle;
}
private:
native_type m_handle;
};
#ifdef USE_SRWLOCKS
class mutex
{
#ifdef _WIN32
typedef SRWLOCK native_type;
#else
typedef pthread_mutex_t native_type;
#endif
public:
typedef native_type* native_handle_type;
mutex(const mutex&) /*= delete*/;
mutex& operator=(const mutex&) /*= delete*/;
mutex()
{
#ifdef _WIN32
InitializeSRWLock(&m_handle);
#else
pthread_mutex_init(&m_handle, NULL);
#endif
}
~mutex()
{
#ifdef _WIN32
#else
pthread_mutex_destroy(&m_handle);
#endif
}
void lock()
{
#ifdef _WIN32
AcquireSRWLockExclusive(&m_handle);
#else
pthread_mutex_lock(&m_handle);
#endif
}
void unlock()
{
#ifdef _WIN32
ReleaseSRWLockExclusive(&m_handle);
#else
pthread_mutex_unlock(&m_handle);
#endif
}
bool try_lock()
{
#ifdef _WIN32
return (0 != TryAcquireSRWLockExclusive(&m_handle));
#else
return !pthread_mutex_trylock(&m_handle);
#endif
}
native_handle_type native_handle()
{
return &m_handle;
}
private:
native_type m_handle;
};
#else
typedef recursive_mutex mutex; // just use CriticalSections
#endif
enum defer_lock_t { defer_lock };
enum try_to_lock_t { try_to_lock };
enum adopt_lock_t { adopt_lock };
template <class Mutex>
class lock_guard
{
public:
typedef Mutex mutex_type;
explicit lock_guard(mutex_type& m)
: pm(m)
{
m.lock();
}
lock_guard(mutex_type& m, adopt_lock_t)
: pm(m)
{
}
~lock_guard()
{
pm.unlock();
}
lock_guard(lock_guard const&) /*= delete*/;
lock_guard& operator=(lock_guard const&) /*= delete*/;
private:
mutex_type& pm;
};
template <class Mutex>
class unique_lock
{
public:
typedef Mutex mutex_type;
unique_lock()
: pm(NULL), owns(false)
{}
/*explicit*/ unique_lock(mutex_type& m)
: pm(&m), owns(true)
{
m.lock();
}
unique_lock(mutex_type& m, defer_lock_t)
: pm(&m), owns(false)
{}
unique_lock(mutex_type& m, try_to_lock_t)
: pm(&m), owns(m.try_lock())
{}
unique_lock(mutex_type& m, adopt_lock_t)
: pm(&m), owns(true)
{}
//template <class Clock, class Duration>
//unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
//template <class Rep, class Period>
//unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
~unique_lock()
{
if (owns_lock())
mutex()->unlock();
}
#ifdef USE_RVALUE_REFERENCES
unique_lock& operator=(const unique_lock&) /*= delete*/;
unique_lock& operator=(unique_lock&& other)
{
#else
unique_lock& operator=(const unique_lock& u)
{
// ugly const_cast to get around lack of rvalue references
unique_lock& other = const_cast<unique_lock&>(u);
#endif
swap(other);
return *this;
}
#ifdef USE_RVALUE_REFERENCES
unique_lock(const unique_lock&) /*= delete*/;
unique_lock(unique_lock&& other)
: pm(NULL), owns(false)
{
#else
unique_lock(const unique_lock& u)
: pm(NULL), owns(false)
{
// ugly const_cast to get around lack of rvalue references
unique_lock& other = const_cast<unique_lock&>(u);
#endif
swap(other);
}
void lock()
{
mutex()->lock();
owns = true;
}
bool try_lock()
{
owns = mutex()->try_lock();
return owns;
}
//template <class Rep, class Period>
//bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
//template <class Clock, class Duration>
//bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock()
{
mutex()->unlock();
owns = false;
}
void swap(unique_lock& u)
{
std::swap(pm, u.pm);
std::swap(owns, u.owns);
}
mutex_type* release()
{
return mutex();
pm = NULL;
owns = false;
}
bool owns_lock() const
{
return owns;
}
//explicit operator bool () const
//{
// return owns_lock();
//}
mutex_type* mutex() const
{
return pm;
}
private:
mutex_type* pm;
bool owns;
};
template <class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
{
x.swap(y);
}
}
#endif
#endif

View file

@ -55,164 +55,6 @@ void SetCurrentThreadAffinity(u32 mask)
SetThreadAffinityMask(GetCurrentThread(), mask); SetThreadAffinityMask(GetCurrentThread(), mask);
} }
CriticalSection::CriticalSection(int spincount)
{
if (spincount)
{
if (!InitializeCriticalSectionAndSpinCount(&section, spincount))
ERROR_LOG(COMMON, "CriticalSection could not be initialized!\n%s", GetLastErrorMsg());
}
else
{
InitializeCriticalSection(&section);
}
}
CriticalSection::~CriticalSection()
{
DeleteCriticalSection(&section);
}
void CriticalSection::Enter()
{
EnterCriticalSection(&section);
}
bool CriticalSection::TryEnter()
{
return TryEnterCriticalSection(&section) ? true : false;
}
void CriticalSection::Leave()
{
LeaveCriticalSection(&section);
}
EventEx::EventEx()
{
InterlockedExchange(&m_Lock, 1);
}
void EventEx::Init()
{
InterlockedExchange(&m_Lock, 1);
}
void EventEx::Shutdown()
{
InterlockedExchange(&m_Lock, 0);
}
void EventEx::Set()
{
InterlockedExchange(&m_Lock, 0);
}
void EventEx::Spin()
{
while (InterlockedCompareExchange(&m_Lock, 1, 0))
// This only yields when there is a runnable thread on this core
// If not, spin
SwitchToThread();
}
void EventEx::Wait()
{
while (InterlockedCompareExchange(&m_Lock, 1, 0))
// This directly enters Ring0 and enforces a sleep about 15ms
SleepCurrentThread(1);
}
bool EventEx::MsgWait()
{
while (InterlockedCompareExchange(&m_Lock, 1, 0))
{
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) return false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// This directly enters Ring0 and enforces a sleep about 15ms
SleepCurrentThread(1);
}
return true;
}
// Regular same thread loop based waiting
Event::Event()
{
m_hEvent = 0;
}
void Event::Init()
{
m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
void Event::Shutdown()
{
CloseHandle(m_hEvent);
m_hEvent = 0;
}
void Event::Set()
{
SetEvent(m_hEvent);
}
bool Event::Wait(const u32 timeout)
{
return WaitForSingleObject(m_hEvent, timeout) != WAIT_OBJECT_0;
}
inline HRESULT MsgWaitForSingleObject(HANDLE handle, DWORD timeout)
{
return MsgWaitForMultipleObjects(1, &handle, FALSE, timeout, 0);
}
void Event::MsgWait()
{
// Adapted from MSDN example http://msdn.microsoft.com/en-us/library/ms687060.aspx
while (true)
{
DWORD result;
MSG msg;
// Read all of the messages in this next loop,
// removing each message as we read it.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// If it is a quit message, exit.
if (msg.message == WM_QUIT)
return;
// Otherwise, dispatch the message.
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Wait for any message sent or posted to this queue
// or for one of the passed handles be set to signaled.
result = MsgWaitForSingleObject(m_hEvent, THREAD_WAIT_TIMEOUT);
// The result tells us the type of event we have.
if (result == (WAIT_OBJECT_0 + 1))
{
// New messages have arrived.
// Continue to the top of the always while loop to
// dispatch them and resume waiting.
continue;
}
else
{
// result == WAIT_OBJECT_0
// Our event got signaled
return;
}
}
}
// Supporting functions // Supporting functions
void SleepCurrentThread(int ms) void SleepCurrentThread(int ms)
{ {
@ -224,46 +66,34 @@ void SetCurrentThreadAffinity(u32 mask)
SwitchToThread(); SwitchToThread();
} }
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero
} THREADNAME_INFO;
// Usage: SetThreadName (-1, "MainThread");
//
// Sets the debugger-visible name of the current thread. // Sets the debugger-visible name of the current thread.
// Uses undocumented (actually, it is now documented) trick. // Uses undocumented (actually, it is now documented) trick.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
// This is implemented much nicer in upcoming msvc++, see: // This is implemented much nicer in upcoming msvc++, see:
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
void SetCurrentThreadName(const TCHAR* szThreadName) void SetCurrentThreadName(const char* szThreadName)
{ {
THREADNAME_INFO info; static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
struct THREADNAME_INFO
{
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero
} info;
#pragma pack(pop)
info.dwType = 0x1000; info.dwType = 0x1000;
#ifdef UNICODE
//TODO: Find the proper way to do this.
char tname[256];
unsigned int i;
for (i = 0; i < _tcslen(szThreadName); i++)
{
tname[i] = (char)szThreadName[i]; //poor man's unicode->ansi, TODO: fix
}
tname[i] = 0;
info.szName = tname;
#else
info.szName = szThreadName; info.szName = szThreadName;
#endif
info.dwThreadID = -1; //dwThreadID; info.dwThreadID = -1; //dwThreadID;
info.dwFlags = 0; info.dwFlags = 0;
__try __try
{ {
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR*)&info); RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} }
__except(EXCEPTION_CONTINUE_EXECUTION) __except(EXCEPTION_CONTINUE_EXECUTION)
{} {}
@ -296,47 +126,6 @@ void SetCurrentThreadAffinity(u32 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;
CriticalSection::CriticalSection(int spincount_unused)
{
pthread_mutex_init(&mutex, NULL);
}
CriticalSection::~CriticalSection()
{
pthread_mutex_destroy(&mutex);
}
void CriticalSection::Enter()
{
#ifdef DEBUG
int ret = pthread_mutex_lock(&mutex);
if (ret) ERROR_LOG(COMMON, "%s: pthread_mutex_lock(%p) failed: %s\n",
__FUNCTION__, &mutex, strerror(ret));
#else
pthread_mutex_lock(&mutex);
#endif
}
bool CriticalSection::TryEnter()
{
return(!pthread_mutex_trylock(&mutex));
}
void CriticalSection::Leave()
{
#ifdef DEBUG
int ret = pthread_mutex_unlock(&mutex);
if (ret) ERROR_LOG(COMMON, "%s: pthread_mutex_unlock(%p) failed: %s\n",
__FUNCTION__, &mutex, strerror(ret));
#else
pthread_mutex_unlock(&mutex);
#endif
}
void SleepCurrentThread(int ms) void SleepCurrentThread(int ms)
{ {
usleep(1000 * ms); usleep(1000 * ms);
@ -357,7 +146,7 @@ void SetCurrentThreadAffinity(u32 mask)
pthread_key_create(&threadname_key, FreeThreadName); pthread_key_create(&threadname_key, FreeThreadName);
} }
void SetCurrentThreadName(const TCHAR* szThreadName) void SetCurrentThreadName(const char* szThreadName)
{ {
pthread_once(&threadname_key_once, ThreadnameKeyAlloc); pthread_once(&threadname_key_once, ThreadnameKeyAlloc);
@ -370,74 +159,6 @@ void SetCurrentThreadAffinity(u32 mask)
INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName); INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName);
} }
Event::Event()
{
is_set_ = false;
}
void Event::Init()
{
pthread_cond_init(&event_, 0);
pthread_mutex_init(&mutex_, 0);
}
void Event::Shutdown()
{
pthread_mutex_destroy(&mutex_);
pthread_cond_destroy(&event_);
}
void Event::Set()
{
pthread_mutex_lock(&mutex_);
if (!is_set_)
{
is_set_ = true;
pthread_cond_signal(&event_);
}
pthread_mutex_unlock(&mutex_);
}
bool Event::Wait(const u32 timeout)
{
bool timedout = false;
struct timespec wait;
pthread_mutex_lock(&mutex_);
if (timeout != INFINITE)
{
memset(&wait, 0, sizeof(wait));
struct timeval now;
gettimeofday(&now, NULL);
wait.tv_nsec = (now.tv_usec + (timeout % 1000)) * 1000;
wait.tv_sec = now.tv_sec + (timeout / 1000);
}
while (!is_set_ && !timedout)
{
if (timeout == INFINITE)
{
pthread_cond_wait(&event_, &mutex_);
}
else
{
timedout = pthread_cond_timedwait(&event_, &mutex_, &wait) == ETIMEDOUT;
}
}
is_set_ = false;
pthread_mutex_unlock(&mutex_);
return timedout;
}
#endif #endif
} // namespace Common } // namespace Common

View file

@ -19,6 +19,8 @@
#define _THREAD_H_ #define _THREAD_H_
#include "StdThread.h" #include "StdThread.h"
#include "StdMutex.h"
#include "StdConditionVariable.h"
// 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"
@ -38,7 +40,6 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
namespace Common namespace Common
{ {
@ -47,87 +48,56 @@ int CurrentThreadId();
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
void SetCurrentThreadAffinity(u32 mask); void SetCurrentThreadAffinity(u32 mask);
class CriticalSection
{
#ifdef _WIN32
CRITICAL_SECTION section;
#else
#ifdef _POSIX_THREADS
pthread_mutex_t mutex;
#endif
#endif
public:
CriticalSection(int spincount = 1000);
~CriticalSection();
void Enter();
bool TryEnter();
void Leave();
};
#ifdef _WIN32
// Event(WaitForSingleObject) is too expensive
// as it always enters Ring0 regardless of the state of lock
// This EventEx will try to stay in Ring3 as much as possible
// If the lock can be obtained in the first time, Ring0 won't be entered at all
class EventEx
{
public:
EventEx();
void Init();
void Shutdown();
void Set();
// Infinite wait
void Spin();
// Infinite wait with sleep
void Wait();
// Wait with message processing and sleep
bool MsgWait();
private:
volatile long m_Lock;
};
#else
// TODO: implement for Linux
#define EventEx Event
#endif
class Event class Event
{ {
public: public:
Event(); void Set()
void Init(); {
void Shutdown(); m_condvar.notify_one();
}
void Set();
//returns whether the wait timed out
bool Wait(const u32 timeout = INFINITE);
#ifdef _WIN32
void MsgWait();
#else
void MsgWait() {Wait();}
#endif
void Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
m_condvar.wait(lk);
}
private: private:
#ifdef _WIN32 std::condition_variable m_condvar;
std::mutex m_mutex;
};
HANDLE m_hEvent; // TODO: doesn't work on windows with (count > 2)
/* If we have waited more than five seconds we can be pretty sure that the thread is deadlocked. class Barrier
So then we can just as well continue and hope for the best. I could try several times that {
this works after a five second timeout (with works meaning that the game stopped and I could public:
start another game without any noticable problems). But several times it failed to, and ended Barrier(size_t count)
with a crash. But it's better than an infinite deadlock. */ : m_count(count), m_waiting(0)
static const int THREAD_WAIT_TIMEOUT = 5000; // INFINITE or 5000 for example {}
#else // block until "count" threads call Wait()
bool Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
bool is_set_; if (m_count == ++m_waiting)
#ifdef _POSIX_THREADS {
pthread_cond_t event_; m_waiting = 0;
pthread_mutex_t mutex_; m_condvar.notify_all();
#endif return true;
}
else
{
m_condvar.wait(lk);
return false;
}
}
#endif private:
std::condition_variable m_condvar;
std::mutex m_mutex;
const size_t m_count;
volatile size_t m_waiting;
}; };
void SleepCurrentThread(int ms); void SleepCurrentThread(int ms);
@ -138,11 +108,7 @@ void SetCurrentThreadAffinity(u32 mask);
// than using events because event functions use kernel calls. // than using events because event functions use kernel calls.
inline void YieldCPU() inline void YieldCPU()
{ {
#ifdef _WIN32 std::this_thread::yield();
Sleep(0);
#elif defined(_M_IX86) || defined(_M_X64)
sleep(0);
#endif
} }
void SetCurrentThreadName(const char *name); void SetCurrentThreadName(const char *name);

View file

@ -102,8 +102,8 @@ static std::thread cpuThread;
SCoreStartupParameter g_CoreStartupParameter; SCoreStartupParameter g_CoreStartupParameter;
// This event is set when the emuthread starts. // This event is set when the emuthread starts.
Common::Event emuThreadGoing; Common::Barrier emuThreadGoing(2);
Common::Event cpuRunloopQuit; Common::Barrier cpuRunloopQuit(2);
std::string GetStateFileName() { return g_stateFileName; } std::string GetStateFileName() { return g_stateFileName; }
void SetStateFileName(std::string val) { g_stateFileName = val; } void SetStateFileName(std::string val) { g_stateFileName = val; }
@ -248,14 +248,11 @@ bool Init()
// The hardware is initialized. // The hardware is initialized.
g_bHwInit = true; g_bHwInit = true;
emuThreadGoing.Init();
// Start the emu thread // Start the emu thread
g_EmuThread = std::thread(EmuThread); g_EmuThread = std::thread(EmuThread);
// Wait until the emu thread is running // Wait until the emu thread is running
emuThreadGoing.MsgWait(); emuThreadGoing.Wait();
emuThreadGoing.Shutdown();
Host_SetWaitCursor(false); Host_SetWaitCursor(false);
@ -359,7 +356,7 @@ void CpuThread()
// Enter CPU run loop. When we leave it - we are done. // Enter CPU run loop. When we leave it - we are done.
CCPU::Run(); CCPU::Run();
cpuRunloopQuit.Set(); cpuRunloopQuit.Wait();
return; return;
} }
@ -372,8 +369,6 @@ void EmuThread()
const SCoreStartupParameter& _CoreParameter = const SCoreStartupParameter& _CoreParameter =
SConfig::GetInstance().m_LocalCoreStartupParameter; SConfig::GetInstance().m_LocalCoreStartupParameter;
cpuRunloopQuit.Init();
Common::SetCurrentThreadName("Emuthread - starting"); Common::SetCurrentThreadName("Emuthread - starting");
if (_CoreParameter.bLockThreads) if (_CoreParameter.bLockThreads)
@ -384,7 +379,7 @@ void EmuThread()
Common::SetCurrentThreadAffinity(2); Common::SetCurrentThreadAffinity(2);
} }
emuThreadGoing.Set(); emuThreadGoing.Wait();
DisplayMessage("CPU: " + cpu_info.Summarize(), 8000); DisplayMessage("CPU: " + cpu_info.Summarize(), 8000);
DisplayMessage(_CoreParameter.m_strFilename, 3000); DisplayMessage(_CoreParameter.m_strFilename, 3000);
@ -462,7 +457,6 @@ void EmuThread()
VolumeHandler::EjectVolume(); VolumeHandler::EjectVolume();
FileMon::Close(); FileMon::Close();
cpuRunloopQuit.Shutdown();
g_bStopping = false; g_bStopping = false;
} }

View file

@ -68,7 +68,7 @@ u64 fakeDecStartTicks;
u64 fakeTBStartValue; u64 fakeTBStartValue;
u64 fakeTBStartTicks; u64 fakeTBStartTicks;
static Common::CriticalSection externalEventSection; static std::mutex externalEventSection;
void (*advanceCallback)(int cyclesExecuted) = NULL; void (*advanceCallback)(int cyclesExecuted) = NULL;
@ -143,19 +143,18 @@ void Shutdown()
delete ev; delete ev;
} }
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
while(eventTsPool) while(eventTsPool)
{ {
Event *ev = eventTsPool; Event *ev = eventTsPool;
eventTsPool = ev->next; eventTsPool = ev->next;
delete ev; delete ev;
} }
externalEventSection.Leave();
} }
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
p.Do(downcount); p.Do(downcount);
p.Do(slicelength); p.Do(slicelength);
p.Do(globalTimer); p.Do(globalTimer);
@ -210,7 +209,6 @@ void DoState(PointerWrap &p)
break; break;
} }
} }
externalEventSection.Leave();
} }
u64 GetTicks() u64 GetTicks()
@ -227,7 +225,7 @@ u64 GetIdleTicks()
// schedule things to be executed on the main thread. // schedule things to be executed on the main thread.
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata) void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata)
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
Event *ne = GetNewTsEvent(); Event *ne = GetNewTsEvent();
ne->time = globalTimer + cyclesIntoFuture; ne->time = globalTimer + cyclesIntoFuture;
ne->type = event_type; ne->type = event_type;
@ -238,7 +236,6 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata
if(tsLast) if(tsLast)
tsLast->next = ne; tsLast->next = ne;
tsLast = ne; tsLast = ne;
externalEventSection.Leave();
} }
// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread
@ -247,9 +244,8 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata)
{ {
if(Core::IsCPUThread()) if(Core::IsCPUThread())
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
event_types[event_type].callback(userdata, 0); event_types[event_type].callback(userdata, 0);
externalEventSection.Leave();
} }
else else
ScheduleEvent_Threadsafe(0, event_type, userdata); ScheduleEvent_Threadsafe(0, event_type, userdata);
@ -352,10 +348,9 @@ void RemoveEvent(int event_type)
void RemoveThreadsafeEvent(int event_type) void RemoveThreadsafeEvent(int event_type)
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
if (!tsFirst) if (!tsFirst)
{ {
externalEventSection.Leave();
return; return;
} }
while(tsFirst) while(tsFirst)
@ -373,7 +368,6 @@ void RemoveThreadsafeEvent(int event_type)
} }
if (!tsFirst) if (!tsFirst)
{ {
externalEventSection.Leave();
return; return;
} }
Event *prev = tsFirst; Event *prev = tsFirst;
@ -392,7 +386,6 @@ void RemoveThreadsafeEvent(int event_type)
ptr = ptr->next; ptr = ptr->next;
} }
} }
externalEventSection.Leave();
} }
void RemoveAllEvents(int event_type) void RemoveAllEvents(int event_type)
@ -438,8 +431,7 @@ void ProcessFifoWaitEvents()
void MoveEvents() void MoveEvents()
{ {
std::lock_guard<std::mutex> lk(externalEventSection);
externalEventSection.Enter();
// Move events from async queue into main queue // Move events from async queue into main queue
while (tsFirst) while (tsFirst)
{ {
@ -458,8 +450,6 @@ void MoveEvents()
eventTsPool = ev; eventTsPool = ev;
allocatedTsEvents--; allocatedTsEvents--;
} }
externalEventSection.Leave();
} }
void Advance() void Advance()

View file

@ -41,7 +41,7 @@ DSPCoreState core_state = DSPCORE_STOP;
u16 cyclesLeft = 0; u16 cyclesLeft = 0;
DSPEmitter *dspjit = NULL; DSPEmitter *dspjit = NULL;
Common::Event step_event; Common::Event step_event;
Common::CriticalSection ExtIntCriticalSection; static std::mutex ExtIntCriticalSection;
static bool LoadRom(const char *fname, int size_in_words, u16 *rom) static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
{ {
@ -165,8 +165,6 @@ bool DSPCore_Init(const char *irom_filename, const char *coef_filename,
DSPAnalyzer::Analyze(); DSPAnalyzer::Analyze();
step_event.Init();
core_state = DSPCORE_RUNNING; core_state = DSPCORE_RUNNING;
return true; return true;
@ -183,7 +181,6 @@ void DSPCore_Shutdown()
delete dspjit; delete dspjit;
dspjit = NULL; dspjit = NULL;
} }
step_event.Shutdown();
DSPCore_FreeMemoryPages(); DSPCore_FreeMemoryPages();
} }
@ -206,9 +203,8 @@ void DSPCore_SetException(u8 level)
// Notify that an external interrupt is pending (used by thread mode) // Notify that an external interrupt is pending (used by thread mode)
void DSPCore_SetExternalInterrupt(bool val) void DSPCore_SetExternalInterrupt(bool val)
{ {
ExtIntCriticalSection.Enter(); std::lock_guard<std::mutex> lk(ExtIntCriticalSection);
g_dsp.external_interrupt_waiting = val; g_dsp.external_interrupt_waiting = val;
ExtIntCriticalSection.Leave();
} }
// Coming from the CPU // Coming from the CPU

View file

@ -249,7 +249,7 @@ struct SDSP
volatile u16 mbox[2][2]; volatile u16 mbox[2][2];
// Mutex protecting the mailbox. // Mutex protecting the mailbox.
Common::CriticalSection g_CriticalSection; std::mutex g_CriticalSection;
// Accelerator / DMA / other hardware registers. Not GPRs. // Accelerator / DMA / other hardware registers. Not GPRs.
u16 ifx_regs[256]; u16 ifx_regs[256];

View file

@ -41,7 +41,7 @@
static void gdsp_do_dma(); static void gdsp_do_dma();
Common::CriticalSection g_CriticalSection; static std::mutex g_CriticalSection;
void gdsp_ifx_init() void gdsp_ifx_init()
{ {
@ -56,35 +56,34 @@ void gdsp_ifx_init()
g_dsp.mbox[1][1] = 0; g_dsp.mbox[1][1] = 0;
} }
u32 gdsp_mbox_peek(u8 mbx) u32 gdsp_mbox_peek(u8 mbx)
{ {
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
u32 value = ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]);
if (DSPHost_OnThread()) return ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]);
g_CriticalSection.Leave();
return value;
} }
void gdsp_mbox_write_h(u8 mbx, u16 val) void gdsp_mbox_write_h(u8 mbx, u16 val)
{ {
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
g_dsp.mbox[mbx][0] = val & 0x7fff;
if (DSPHost_OnThread())
g_CriticalSection.Leave();
}
g_dsp.mbox[mbx][0] = val & 0x7fff;
}
void gdsp_mbox_write_l(u8 mbx, u16 val) void gdsp_mbox_write_l(u8 mbx, u16 val)
{ {
{
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
g_dsp.mbox[mbx][1] = val; g_dsp.mbox[mbx][1] = val;
g_dsp.mbox[mbx][0] |= 0x8000; g_dsp.mbox[mbx][0] |= 0x8000;
if (DSPHost_OnThread()) }
g_CriticalSection.Leave();
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (mbx == GDSP_MBOX_DSP) if (mbx == GDSP_MBOX_DSP)
@ -96,29 +95,27 @@ void gdsp_mbox_write_l(u8 mbx, u16 val)
#endif #endif
} }
u16 gdsp_mbox_read_h(u8 mbx) u16 gdsp_mbox_read_h(u8 mbx)
{ {
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
u16 val = g_dsp.mbox[mbx][0]; // TODO: mask away the top bit?
if (DSPHost_OnThread()) return g_dsp.mbox[mbx][0]; // TODO: mask away the top bit?
g_CriticalSection.Leave();
return val;
} }
u16 gdsp_mbox_read_l(u8 mbx) u16 gdsp_mbox_read_l(u8 mbx)
{ {
u16 val;
{
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
u16 val = g_dsp.mbox[mbx][1]; val = g_dsp.mbox[mbx][1];
g_dsp.mbox[mbx][0] &= ~0x8000; g_dsp.mbox[mbx][0] &= ~0x8000;
}
if (DSPHost_OnThread())
g_CriticalSection.Leave();
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (mbx == GDSP_MBOX_DSP) if (mbx == GDSP_MBOX_DSP)
@ -132,7 +129,6 @@ u16 gdsp_mbox_read_l(u8 mbx)
return val; return val;
} }
void gdsp_ifx_write(u32 addr, u32 val) void gdsp_ifx_write(u32 addr, u32 val)
{ {
switch (addr & 0xff) switch (addr & 0xff)

View file

@ -55,7 +55,7 @@ u32 GeckoCode::Code::GetAddress() const
return gcaddress + (use_po ? pointer_address : (base_address & 0xFE000000)); return gcaddress + (use_po ? pointer_address : (base_address & 0xFE000000));
} }
static Common::CriticalSection active_codes_lock; static std::mutex active_codes_lock;
// currently running code // currently running code
static GeckoCode::Code *codes_start = NULL, *current_code = NULL; static GeckoCode::Code *codes_start = NULL, *current_code = NULL;
@ -78,7 +78,7 @@ bool MathOperation(u32& ret, const u32 left, const u32 right, const u8 type);
void SetActiveCodes(const std::vector<GeckoCode>& gcodes) void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
{ {
active_codes_lock.Enter(); std::lock_guard<std::mutex> lk(active_codes_lock);
active_codes.clear(); active_codes.clear();
// add enabled codes // add enabled codes
@ -94,8 +94,6 @@ void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
} }
inserted_asm_codes.clear(); inserted_asm_codes.clear();
active_codes_lock.Leave();
} }
bool RunGeckoCode(GeckoCode& gecko_code) bool RunGeckoCode(GeckoCode& gecko_code)
@ -151,10 +149,9 @@ bool RunGeckoCode(GeckoCode& gecko_code)
bool RunActiveCodes() bool RunActiveCodes()
{ {
if (false == SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
return true; {
if (false == active_codes_lock.TryEnter()) std::lock_guard<std::mutex> lk(active_codes_lock);
return true;
std::vector<GeckoCode>::iterator std::vector<GeckoCode>::iterator
gcodes_iter = active_codes.begin(), gcodes_iter = active_codes.begin(),
@ -167,8 +164,8 @@ bool RunActiveCodes()
//if (false == RunGeckoCode(*gcodes_iter)) //if (false == RunGeckoCode(*gcodes_iter))
//return false; //return false;
} }
}
active_codes_lock.Leave();
return true; return true;
} }

View file

@ -35,7 +35,6 @@ namespace
void CCPU::Init(int cpu_core) void CCPU::Init(int cpu_core)
{ {
m_StepEvent.Init();
PowerPC::Init(cpu_core); PowerPC::Init(cpu_core);
m_SyncEvent = 0; m_SyncEvent = 0;
} }
@ -43,7 +42,6 @@ void CCPU::Init(int cpu_core)
void CCPU::Shutdown() void CCPU::Shutdown()
{ {
PowerPC::Shutdown(); PowerPC::Shutdown();
m_StepEvent.Shutdown();
m_SyncEvent = 0; m_SyncEvent = 0;
} }

View file

@ -570,7 +570,7 @@ void CUCode_Zelda::ExecuteList()
void CUCode_Zelda::DoState(PointerWrap &p) void CUCode_Zelda::DoState(PointerWrap &p)
{ {
// It's bad if we try to save during Mix() // It's bad if we try to save during Mix()
m_csMix.Enter(); std::lock_guard<std::mutex> lk(m_csMix);
p.Do(m_CRC); p.Do(m_CRC);
@ -618,6 +618,4 @@ void CUCode_Zelda::DoState(PointerWrap &p)
p.Do(m_UploadSetupInProgress); p.Do(m_UploadSetupInProgress);
m_rMailHandler.DoState(p); m_rMailHandler.DoState(p);
m_csMix.Leave();
} }

View file

@ -746,7 +746,7 @@ ContinueWithBlock:
// size is in stereo samples. // size is in stereo samples.
void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) void CUCode_Zelda::MixAdd(short *_Buffer, int _Size)
{ {
m_csMix.Enter(); std::lock_guard<std::mutex> lk(m_csMix);
// Safety check // Safety check
if (_Size > 256 * 1024 - 8) if (_Size > 256 * 1024 - 8)
_Size = 256 * 1024 - 8; _Size = 256 * 1024 - 8;
@ -793,5 +793,4 @@ void CUCode_Zelda::MixAdd(short *_Buffer, int _Size)
_Buffer += 2; _Buffer += 2;
} }
m_csMix.Leave();
} }

View file

@ -86,7 +86,7 @@ protected:
bool NeedsResumeMail(); bool NeedsResumeMail();
CMailHandler& m_rMailHandler; CMailHandler& m_rMailHandler;
Common::CriticalSection m_csMix; std::mutex m_csMix;
enum EDSP_Codes enum EDSP_Codes
{ {

View file

@ -215,7 +215,7 @@ static unsigned char media_buffer[0x40];
// Needed because data and streaming audio access needs to be managed by the "drive" // Needed because data and streaming audio access needs to be managed by the "drive"
// (both requests can happen at the same time, audio takes precedence) // (both requests can happen at the same time, audio takes precedence)
Common::CriticalSection dvdread_section; static std::mutex dvdread_section;
static int ejectDisc; static int ejectDisc;
static int insertDisc; static int insertDisc;
@ -345,10 +345,8 @@ void ClearCoverInterrupt()
bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength) bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength)
{ {
// We won't need the crit sec when DTK streaming has been rewritten correctly. // We won't need the crit sec when DTK streaming has been rewritten correctly.
dvdread_section.Enter(); std::lock_guard<std::mutex> lk(dvdread_section);
bool retval = VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength); return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength);
dvdread_section.Leave();
return retval;
} }
bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples) bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
@ -360,9 +358,10 @@ bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
return false; return false;
} }
_iNumSamples &= ~31; _iNumSamples &= ~31;
dvdread_section.Enter(); {
std::lock_guard<std::mutex> lk(dvdread_section);
VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples); VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples);
dvdread_section.Leave(); }
// //
// FIX THIS // FIX THIS

View file

@ -26,7 +26,7 @@ int GeckoSockServer::client_count;
std::thread GeckoSockServer::connectionThread; 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; std::mutex GeckoSockServer::connection_lock;
GeckoSockServer::GeckoSockServer() GeckoSockServer::GeckoSockServer()
: client_running(false) : client_running(false)
@ -76,9 +76,8 @@ void GeckoSockServer::GeckoConnectionWaiter()
{ {
if (server.Accept(new_client) == sf::Socket::Done) if (server.Accept(new_client) == sf::Socket::Done)
{ {
connection_lock.Enter(); std::lock_guard<std::mutex> lk(connection_lock);
waiting_socks.push(new_client); waiting_socks.push(new_client);
connection_lock.Leave();
} }
SLEEP(1); SLEEP(1);
} }
@ -89,7 +88,8 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
{ {
bool sock_filled = false; bool sock_filled = false;
connection_lock.Enter(); std::lock_guard<std::mutex> lk(connection_lock);
if (waiting_socks.size()) if (waiting_socks.size())
{ {
sock_to_fill = waiting_socks.front(); sock_to_fill = waiting_socks.front();
@ -106,7 +106,6 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
waiting_socks.pop(); waiting_socks.pop();
sock_filled = true; sock_filled = true;
} }
connection_lock.Leave();
return sock_filled; return sock_filled;
} }
@ -124,7 +123,9 @@ void GeckoSockServer::ClientThread()
u8 data; u8 data;
std::size_t got = 0; std::size_t got = 0;
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
if (client.Receive((char*)&data, sizeof(data), got) if (client.Receive((char*)&data, sizeof(data), got)
== sf::Socket::Disconnected) == sf::Socket::Disconnected)
client_running = false; client_running = false;
@ -138,7 +139,8 @@ void GeckoSockServer::ClientThread()
client_running = false; client_running = false;
send_fifo.pop(); send_fifo.pop();
} }
transfer_lock.Leave(); } // unlock transfer
SLEEP(1); SLEEP(1);
} }
@ -173,35 +175,40 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
// PC -> Gecko // PC -> Gecko
// |= 0x08000000 if successful // |= 0x08000000 if successful
case CMD_RECV: case CMD_RECV:
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
if (!recv_fifo.empty()) if (!recv_fifo.empty())
{ {
_uData = 0x08000000 | (recv_fifo.front() << 16); _uData = 0x08000000 | (recv_fifo.front() << 16);
recv_fifo.pop(); recv_fifo.pop();
} }
transfer_lock.Leave();
break; break;
}
// Gecko -> PC // Gecko -> PC
// |= 0x04000000 if successful // |= 0x04000000 if successful
case CMD_SEND: case CMD_SEND:
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
send_fifo.push(_uData >> 20); send_fifo.push(_uData >> 20);
transfer_lock.Leave();
_uData = 0x04000000; _uData = 0x04000000;
break; break;
}
// Check if ok for Gecko -> PC, or FIFO full // Check if ok for Gecko -> PC, or FIFO full
// |= 0x04000000 if FIFO is not full // |= 0x04000000 if FIFO is not full
case CMD_CHK_TX: case CMD_CHK_TX:
_uData = 0x04000000; _uData = 0x04000000;
break; break;
// Check if data in FIFO for PC -> Gecko, or FIFO empty // Check if data in FIFO for PC -> Gecko, or FIFO empty
// |= 0x04000000 if data in recv FIFO // |= 0x04000000 if data in recv FIFO
case CMD_CHK_RX: case CMD_CHK_RX:
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
_uData = recv_fifo.empty() ? 0 : 0x04000000; _uData = recv_fifo.empty() ? 0 : 0x04000000;
transfer_lock.Leave();
break; break;
}
default: default:
ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData); ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData);

View file

@ -34,7 +34,7 @@ public:
sf::SocketTCP client; sf::SocketTCP client;
void ClientThread(); void ClientThread();
std::thread clientThread; std::thread clientThread;
Common::CriticalSection transfer_lock; std::mutex transfer_lock;
std::queue<u8> send_fifo; std::queue<u8> send_fifo;
std::queue<u8> recv_fifo; std::queue<u8> recv_fifo;
@ -50,7 +50,7 @@ private:
static volatile bool server_running; static volatile bool server_running;
static std::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 std::mutex connection_lock;
}; };
class CEXIGecko class CEXIGecko

View file

@ -65,8 +65,9 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// wtf is this? // wtf is this?
_pPADStatus->button = PAD_USE_ORIGIN; _pPADStatus->button = PAD_USE_ORIGIN;
// try lock std::unique_lock<std::mutex> lk(g_plugin.controls_lock, std::try_to_lock);
if (false == g_plugin.controls_crit.TryEnter())
if (!lk.owns_lock())
{ {
// if gui has lock (messing with controls), skip this input cycle // if gui has lock (messing with controls), skip this input cycle
// center axes and return // center axes and return
@ -86,9 +87,6 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// get input // get input
((GCPad*)g_plugin.controllers[_numPAD])->GetInput(_pPADStatus); ((GCPad*)g_plugin.controllers[_numPAD])->GetInput(_pPADStatus);
// leave
g_plugin.controls_crit.Leave();
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
@ -99,15 +97,13 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// //
void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{ {
// enter std::unique_lock<std::mutex> lk(g_plugin.controls_lock, std::try_to_lock);
if ( g_plugin.controls_crit.TryEnter() )
if (!lk.owns_lock())
{ {
// TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time // TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time
// set rumble // set rumble
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 ); ((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 );
// leave
g_plugin.controls_crit.Leave();
} }
} }

View file

@ -24,7 +24,7 @@
static std::thread connectionThread; static std::thread connectionThread;
static std::queue<sf::SocketTCP> waiting_socks; static std::queue<sf::SocketTCP> waiting_socks;
static Common::CriticalSection cs_gba; static std::mutex cs_gba;
namespace { volatile bool server_running; } namespace { volatile bool server_running; }
// --- GameBoy Advance "Link Cable" --- // --- GameBoy Advance "Link Cable" ---
@ -47,9 +47,8 @@ void GBAConnectionWaiter()
{ {
if (server.Accept(new_client) == sf::Socket::Done) if (server.Accept(new_client) == sf::Socket::Done)
{ {
cs_gba.Enter(); std::lock_guard<std::mutex> lk(cs_gba);
waiting_socks.push(new_client); waiting_socks.push(new_client);
cs_gba.Leave();
} }
SLEEP(1); SLEEP(1);
} }
@ -68,14 +67,14 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
{ {
bool sock_filled = false; bool sock_filled = false;
cs_gba.Enter(); std::lock_guard<std::mutex> lk(cs_gba);
if (waiting_socks.size()) if (waiting_socks.size())
{ {
sock_to_fill = waiting_socks.front(); sock_to_fill = waiting_socks.front();
waiting_socks.pop(); waiting_socks.pop();
sock_filled = true; sock_filled = true;
} }
cs_gba.Leave();
return sock_filled; return sock_filled;
} }

View file

@ -93,8 +93,8 @@ void Update(int _number)
{ {
//PanicAlert( "Wiimote_Update" ); //PanicAlert( "Wiimote_Update" );
// TODO: change this to a TryEnter, and make it give empty input on failure // TODO: change this to a try_to_lock, and make it give empty input on failure
g_plugin.controls_crit.Enter(); std::lock_guard<std::mutex> lk(g_plugin.controls_lock);
static int _last_number = 4; static int _last_number = 4;
if (_number <= _last_number) if (_number <= _last_number)
@ -108,8 +108,6 @@ void Update(int _number)
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update(); ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update();
else else
WiimoteReal::Update(_number); WiimoteReal::Update(_number);
g_plugin.controls_crit.Leave();
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________

View file

@ -248,14 +248,14 @@ void Wiimote::RequestStatus(const wm_request_status* const rs)
{ {
using namespace WiimoteReal; using namespace WiimoteReal;
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index]) if (g_wiimotes[m_index])
{ {
wm_request_status rpt; wm_request_status rpt;
rpt.rumble = 0; rpt.rumble = 0;
g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
} }
g_refresh_critsec.Leave();
return; return;
} }

View file

@ -661,7 +661,7 @@ void Wiimote::Update()
{ {
using namespace WiimoteReal; using namespace WiimoteReal;
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index]) if (g_wiimotes[m_index])
{ {
Report rpt = g_wiimotes[m_index]->ProcessReadQueue(); Report rpt = g_wiimotes[m_index]->ProcessReadQueue();
@ -736,7 +736,6 @@ void Wiimote::Update()
delete[] real_data; delete[] real_data;
} }
} }
g_refresh_critsec.Leave();
} }
if (Frame::IsRecordingInput()) if (Frame::IsRecordingInput())
{ {

View file

@ -35,7 +35,7 @@ namespace WiimoteReal
bool g_real_wiimotes_initialized = false; bool g_real_wiimotes_initialized = false;
unsigned int g_wiimotes_found = 0; unsigned int g_wiimotes_found = 0;
Common::CriticalSection g_refresh_critsec; std::mutex g_refresh_lock;
Wiimote *g_wiimotes[MAX_WIIMOTES]; Wiimote *g_wiimotes[MAX_WIIMOTES];
@ -439,11 +439,11 @@ void Shutdown(void)
// This is called from the GUI thread // This is called from the GUI thread
void Refresh() void Refresh()
{ {
std::lock_guard<std::mutex> lk(g_refresh_lock);
#ifdef _WIN32 #ifdef _WIN32
g_refresh_critsec.Enter();
Shutdown(); Shutdown();
Initialize(); Initialize();
g_refresh_critsec.Leave();
#else #else
// Make sure real wiimotes have been initialized // Make sure real wiimotes have been initialized
if (!g_real_wiimotes_initialized) if (!g_real_wiimotes_initialized)
@ -458,8 +458,6 @@ void Refresh()
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
++wanted_wiimotes; ++wanted_wiimotes;
g_refresh_critsec.Enter();
// Remove wiimotes that are paired with slots no longer configured for a // Remove wiimotes that are paired with slots no longer configured for a
// real wiimote or that are disconnected // real wiimote or that are disconnected
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
@ -486,50 +484,40 @@ void Refresh()
g_wiimotes_found = num_wiimotes; g_wiimotes_found = num_wiimotes;
} }
g_refresh_critsec.Leave();
#endif #endif
} }
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{ {
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber]) if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
g_refresh_critsec.Leave();
} }
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{ {
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber]) if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size);
g_refresh_critsec.Leave();
} }
// Read the Wiimote once // Read the Wiimote once
void Update(int _WiimoteNumber) void Update(int _WiimoteNumber)
{ {
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber]) if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->Update(); g_wiimotes[_WiimoteNumber]->Update();
g_refresh_critsec.Leave();
} }
void StateChange(EMUSTATE_CHANGE newState) void StateChange(EMUSTATE_CHANGE newState)
{ {
//g_refresh_critsec.Enter(); // enter //std::lock_guard<std::mutex> lk(g_refresh_lock);
// TODO: disable/enable auto reporting, maybe // TODO: disable/enable auto reporting, maybe
//g_refresh_critsec.Leave(); // leave
} }
}; // end of namespace }; // end of namespace

View file

@ -101,7 +101,7 @@ private:
Common::FifoQueue<Report> m_audio_reports; Common::FifoQueue<Report> m_audio_reports;
}; };
extern Common::CriticalSection g_refresh_critsec; extern std::mutex g_refresh_lock;
extern Wiimote *g_wiimotes[4]; extern Wiimote *g_wiimotes[4];
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);

View file

@ -27,7 +27,7 @@
// for wiimote/ OSD messages // for wiimote/ OSD messages
#include "Core.h" #include "Core.h"
Common::CriticalSection crit_netplay_ptr; std::mutex crit_netplay_ptr;
static NetPlay* netplay_ptr = NULL; static NetPlay* netplay_ptr = NULL;
#define RPT_SIZE_HACK (1 << 16) #define RPT_SIZE_HACK (1 << 16)
@ -42,20 +42,20 @@ NetPlay::NetPlay(NetPlayUI* dialog)
void NetPlay_Enable(NetPlay* const np) void NetPlay_Enable(NetPlay* const np)
{ {
CritLocker crit(crit_netplay_ptr); // probably safe without a lock std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = np; netplay_ptr = np;
} }
void NetPlay_Disable() void NetPlay_Disable()
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = NULL; netplay_ptr = NULL;
} }
// called from ---GUI--- thread // called from ---GUI--- thread
NetPlay::~NetPlay() NetPlay::~NetPlay()
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = NULL; netplay_ptr = NULL;
// not perfect // not perfect
@ -116,7 +116,8 @@ void NetPlay::ClearBuffers()
// called from ---CPU--- thread // called from ---CPU--- thread
bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues) bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues)
{ {
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
// in game mapping for this local pad // in game mapping for this local pad
unsigned int in_game_num = m_local_player->pad_map[pad_nb]; unsigned int in_game_num = m_local_player->pad_map[pad_nb];
@ -138,7 +139,7 @@ bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, Ne
} }
} }
m_crit.players.Leave(); } // unlock players
//Common::Timer bufftimer; //Common::Timer bufftimer;
//bufftimer.Start(); //bufftimer.Start();
@ -181,14 +182,13 @@ void NetPlay::WiimoteInput(int _number, u16 _channelID, const void* _pData, u32
m_wiimote_input[_number].back().assign((char*)_pData, (char*)_pData + _Size); m_wiimote_input[_number].back().assign((char*)_pData, (char*)_pData + _Size);
m_wiimote_input[_number].back().channel = _channelID; m_wiimote_input[_number].back().channel = _channelID;
} }
m_crit.players.Leave();
} }
// called from ---CPU--- thread // called from ---CPU--- thread
void NetPlay::WiimoteUpdate(int _number) void NetPlay::WiimoteUpdate(int _number)
{ {
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
// in game mapping for this local wiimote // in game mapping for this local wiimote
unsigned int in_game_num = m_local_player->pad_map[_number]; // just using gc pad_map for now unsigned int in_game_num = m_local_player->pad_map[_number]; // just using gc pad_map for now
@ -203,7 +203,7 @@ void NetPlay::WiimoteUpdate(int _number)
m_wiimote_input[_number].clear(); m_wiimote_input[_number].clear();
} }
m_crit.players.Leave(); } // unlock players
if (0 == m_wiimote_buffer[_number].Size()) if (0 == m_wiimote_buffer[_number].Size())
{ {
@ -251,7 +251,7 @@ bool NetPlay::StartGame(const std::string &path)
// called from ---GUI--- thread and ---NETPLAY--- thread (client side) // called from ---GUI--- thread and ---NETPLAY--- thread (client side)
bool NetPlay::StopGame() bool NetPlay::StopGame()
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (false == m_is_running) if (false == m_is_running)
{ {
@ -288,7 +288,7 @@ u8 NetPlay::GetPadNum(u8 numPAD)
// Actual Core function which is called on every frame // Actual Core function which is called on every frame
bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus); return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus);
@ -300,7 +300,7 @@ bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u
// so all players' games get the same time // so all players' games get the same time
u32 CEXIIPL::NetPlay_GetGCTime() u32 CEXIIPL::NetPlay_GetGCTime()
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
return 1272737767; // watev return 1272737767; // watev
@ -312,7 +312,7 @@ u32 CEXIIPL::NetPlay_GetGCTime()
// return the local pad num that should rumble given a ingame pad num // return the local pad num that should rumble given a ingame pad num
u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD) u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD)
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
return netplay_ptr->GetPadNum(numPAD); return netplay_ptr->GetPadNum(numPAD);
@ -348,7 +348,7 @@ int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number)
//bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size) //bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size)
bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&) bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&)
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
//{ //{

View file

@ -75,19 +75,6 @@ enum
CON_ERR_VERSION_MISMATCH CON_ERR_VERSION_MISMATCH
}; };
// something like this should be in Common stuff
class CritLocker
{
public:
//CritLocker(const CritLocker&);
CritLocker& operator=(const CritLocker&);
CritLocker(Common::CriticalSection& crit) : m_crit(crit) { m_crit.Enter(); }
~CritLocker() { m_crit.Leave(); }
private:
Common::CriticalSection& m_crit;
};
class NetPlayUI class NetPlayUI
{ {
public: public:
@ -135,9 +122,9 @@ protected:
struct struct
{ {
Common::CriticalSection game; std::recursive_mutex game;
// lock order // lock order
Common::CriticalSection players, send; std::recursive_mutex players, send;
} m_crit; } m_crit;
class Player class Player

View file

@ -93,9 +93,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> player.name; packet >> player.name;
packet >> player.revision; packet >> player.revision;
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players[player.pid] = player; m_players[player.pid] = player;
m_crit.players.Leave(); }
m_dialog->Update(); m_dialog->Update();
} }
@ -106,9 +107,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
PlayerId pid; PlayerId pid;
packet >> pid; packet >> pid;
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players.erase(m_players.find(pid)); m_players.erase(m_players.find(pid));
m_crit.players.Leave(); }
m_dialog->Update(); m_dialog->Update();
} }
@ -137,12 +139,13 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
PlayerId pid; PlayerId pid;
packet >> pid; packet >> pid;
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
Player& player = m_players[pid]; Player& player = m_players[pid];
for (unsigned int i=0; i<4; ++i) for (unsigned int i=0; i<4; ++i)
packet >> player.pad_map[i]; packet >> player.pad_map[i];
m_crit.players.Leave(); }
m_dialog->Update(); m_dialog->Update();
} }
@ -171,10 +174,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_CHANGE_GAME : case NP_MSG_CHANGE_GAME :
{ {
// lock here? {
m_crit.game.Enter(); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
packet >> m_selected_game; packet >> m_selected_game;
m_crit.game.Leave(); }
// update gui // update gui
m_dialog->OnMsgChangeGame(m_selected_game); m_dialog->OnMsgChangeGame(m_selected_game);
@ -183,9 +186,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_START_GAME : case NP_MSG_START_GAME :
{ {
m_crit.game.Enter(); // lock buffer {
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
packet >> m_current_game; packet >> m_current_game;
m_crit.game.Leave(); }
m_dialog->OnMsgStartGame(); m_dialog->OnMsgStartGame();
} }
@ -200,7 +204,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_DISABLE_GAME : case NP_MSG_DISABLE_GAME :
{ {
PanicAlertT("Other client disconnected while game is running!! NetPlay is disabled. You manually stop the game."); PanicAlertT("Other client disconnected while game is running!! NetPlay is disabled. You manually stop the game.");
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_is_running = false; m_is_running = false;
NetPlay_Disable(); NetPlay_Disable();
} }
@ -215,7 +219,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
spac << (MessageId)NP_MSG_PONG; spac << (MessageId)NP_MSG_PONG;
spac << ping_key; spac << ping_key;
CritLocker send_lock(m_crit.send); std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
} }
break; break;
@ -263,7 +267,7 @@ void NetPlayClient::ThreadFunc()
// called from ---GUI--- thread // called from ---GUI--- thread
void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list) void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list)
{ {
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::ostringstream ss; std::ostringstream ss;
@ -287,7 +291,7 @@ void NetPlayClient::SendChatMessage(const std::string& msg)
spac << (MessageId)NP_MSG_CHAT_MESSAGE; spac << (MessageId)NP_MSG_CHAT_MESSAGE;
spac << msg; spac << msg;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
} }
@ -300,14 +304,14 @@ void NetPlayClient::SendPadState(const PadMapping local_nb, const NetPad& np)
spac << local_nb; // local pad num spac << local_nb; // local pad num
spac << np.nHi << np.nLo; spac << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
} }
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayClient::StartGame(const std::string &path) bool NetPlayClient::StartGame(const std::string &path)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (false == NetPlay::StartGame(path)) if (false == NetPlay::StartGame(path))
return false; return false;
@ -317,7 +321,7 @@ bool NetPlayClient::StartGame(const std::string &path)
spac << (MessageId)NP_MSG_START_GAME; spac << (MessageId)NP_MSG_START_GAME;
spac << m_current_game; spac << m_current_game;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
return true; return true;

View file

@ -60,8 +60,7 @@ void NetPlayServer::ThreadFunc()
spac << (MessageId)NP_MSG_PING; spac << (MessageId)NP_MSG_PING;
spac << m_ping_key; spac << m_ping_key;
//CritLocker player_lock(m_crit.players); std::lock_guard<std::recursive_mutex> lks(m_crit.send);
CritLocker send_lock(m_crit.send);
m_ping_timer.Start(); m_ping_timer.Start();
SendToClients(spac); SendToClients(spac);
@ -80,9 +79,11 @@ void NetPlayServer::ThreadFunc()
sf::SocketTCP accept_socket; sf::SocketTCP accept_socket;
m_socket.Accept(accept_socket); m_socket.Accept(accept_socket);
m_crit.game.Enter(); // lock game state unsigned int error;
const unsigned int error = OnConnect(accept_socket); {
m_crit.game.Leave(); std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
error = OnConnect(accept_socket);
}
if (error) if (error)
{ {
@ -108,14 +109,15 @@ void NetPlayServer::ThreadFunc()
//case sf::Socket::Disconnected : //case sf::Socket::Disconnected :
default : default :
m_crit.game.Enter(); // lock game state {
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
OnDisconnect(ready_socket); OnDisconnect(ready_socket);
m_crit.game.Leave();
break; break;
} }
} }
} }
} }
}
// close listening socket and client sockets // close listening socket and client sockets
{ {
@ -200,8 +202,8 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
} }
// ENTER {
m_crit.send.Enter(); std::lock_guard<std::recursive_mutex> lks(m_crit.send);
// send join message to already connected clients // send join message to already connected clients
sf::Packet spac; sf::Packet spac;
@ -230,16 +232,16 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
socket.Send(spac); socket.Send(spac);
} }
// LEAVE } // unlock send
m_crit.send.Leave();
// add client to the player list // add client to the player list
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players[socket] = player; m_players[socket] = player;
m_crit.send.Enter(); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone UpdatePadMapping(); // sync pad mappings with everyone
m_crit.send.Leave(); }
m_crit.players.Leave();
// add client to selector/ used for receiving // add client to selector/ used for receiving
m_selector.Add(socket); m_selector.Add(socket);
@ -255,14 +257,14 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
if (m_is_running) if (m_is_running)
{ {
PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must manually stop the game."); PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must manually stop the game.");
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_is_running = false; m_is_running = false;
NetPlay_Disable(); NetPlay_Disable();
sf::Packet spac; sf::Packet spac;
spac << (MessageId)NP_MSG_DISABLE_GAME; spac << (MessageId)NP_MSG_DISABLE_GAME;
// this thread doesnt need players lock // this thread doesnt need players lock
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
@ -272,11 +274,11 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
m_selector.Remove(socket); m_selector.Remove(socket);
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players.erase(m_players.find(socket)); m_players.erase(m_players.find(socket));
// alert other players of disconnect // alert other players of disconnect
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
m_dialog->Update(); m_dialog->Update();
@ -287,7 +289,7 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::GetPadMapping(const int pid, int map[]) bool NetPlayServer::GetPadMapping(const int pid, int map[])
{ {
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::const_iterator std::map<sf::SocketTCP, Client>::const_iterator
i = m_players.begin(), i = m_players.begin(),
e = m_players.end(); e = m_players.end();
@ -309,11 +311,11 @@ bool NetPlayServer::GetPadMapping(const int pid, int map[])
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::SetPadMapping(const int pid, const int map[]) bool NetPlayServer::SetPadMapping(const int pid, const int map[])
{ {
CritLocker game_lock(m_crit.game); // lock game std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (m_is_running) if (m_is_running)
return false; return false;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::iterator std::map<sf::SocketTCP, Client>::iterator
i = m_players.begin(), i = m_players.begin(),
e = m_players.end(); e = m_players.end();
@ -340,7 +342,7 @@ bool NetPlayServer::SetPadMapping(const int pid, const int map[])
i->second.pad_map[p] = -1; i->second.pad_map[p] = -1;
} }
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone UpdatePadMapping(); // sync pad mappings with everyone
m_dialog->Update(); m_dialog->Update();
@ -369,7 +371,7 @@ void NetPlayServer::UpdatePadMapping()
// called from ---GUI--- thread and ---NETPLAY--- thread // called from ---GUI--- thread and ---NETPLAY--- thread
u64 NetPlayServer::CalculateMinimumBufferTime() u64 NetPlayServer::CalculateMinimumBufferTime()
{ {
CritLocker player_lock(m_crit.players); std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::const_iterator std::map<sf::SocketTCP, Client>::const_iterator
i = m_players.begin(), i = m_players.begin(),
@ -392,7 +394,7 @@ u64 NetPlayServer::CalculateMinimumBufferTime()
// called from ---GUI--- thread and ---NETPLAY--- thread // called from ---GUI--- thread and ---NETPLAY--- thread
void NetPlayServer::AdjustPadBufferSize(unsigned int size) void NetPlayServer::AdjustPadBufferSize(unsigned int size)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_target_buffer_size = size; m_target_buffer_size = size;
@ -401,8 +403,8 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size)
spac << (MessageId)NP_MSG_PAD_BUFFER; spac << (MessageId)NP_MSG_PAD_BUFFER;
spac << (u32)m_target_buffer_size; spac << (u32)m_target_buffer_size;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
@ -429,9 +431,10 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
spac << player.pid; spac << player.pid;
spac << msg; spac << msg;
m_crit.send.Enter(); // lock send {
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid); SendToClients(spac, player.pid);
m_crit.send.Leave(); }
// add to gui // add to gui
std::ostringstream ss; std::ostringstream ss;
@ -471,7 +474,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
spac << map; // in game mapping spac << map; // in game mapping
spac << np.nHi << np.nLo; spac << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid); SendToClients(spac, player.pid);
} }
break; break;
@ -510,7 +513,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
// called from ---GUI--- thread // called from ---GUI--- thread
void NetPlayServer::GetPlayerList(std::string& list, std::vector<int>& pid_list) void NetPlayServer::GetPlayerList(std::string& list, std::vector<int>& pid_list)
{ {
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::ostringstream ss; std::ostringstream ss;
@ -534,15 +537,15 @@ void NetPlayServer::SendChatMessage(const std::string& msg)
spac << (PlayerId)0; // server id always 0 spac << (PlayerId)0; // server id always 0
spac << msg; spac << msg;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::ChangeGame(const std::string &game) bool NetPlayServer::ChangeGame(const std::string &game)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_selected_game = game; m_selected_game = game;
@ -551,8 +554,8 @@ bool NetPlayServer::ChangeGame(const std::string &game)
spac << (MessageId)NP_MSG_CHANGE_GAME; spac << (MessageId)NP_MSG_CHANGE_GAME;
spac << game; spac << game;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
return true; return true;
@ -567,14 +570,14 @@ void NetPlayServer::SendPadState(const PadMapping local_nb, const NetPad& np)
spac << m_local_player->pad_map[local_nb]; // in-game pad num spac << m_local_player->pad_map[local_nb]; // in-game pad num
spac << np.nHi << np.nLo; spac << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::StartGame(const std::string &path) bool NetPlayServer::StartGame(const std::string &path)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (false == NetPlay::StartGame(path)) if (false == NetPlay::StartGame(path))
return false; return false;
@ -590,8 +593,8 @@ bool NetPlayServer::StartGame(const std::string &path)
spac << (MessageId)NP_MSG_START_GAME; spac << (MessageId)NP_MSG_START_GAME;
spac << m_current_game; spac << m_current_game;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
return true; return true;
@ -608,8 +611,8 @@ bool NetPlayServer::StopGame()
sf::Packet spac; sf::Packet spac;
spac << (MessageId)NP_MSG_STOP_GAME; spac << (MessageId)NP_MSG_STOP_GAME;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
return true; return true;

View file

@ -36,7 +36,7 @@
#endif #endif
#include "State.h" #include "State.h"
Common::CriticalSection cs_frameSkip; std::mutex cs_frameSkip;
namespace Frame { namespace Frame {
@ -95,7 +95,7 @@ void FrameUpdate()
void SetFrameSkipping(unsigned int framesToSkip) void SetFrameSkipping(unsigned int framesToSkip)
{ {
cs_frameSkip.Enter(); std::lock_guard<std::mutex> lk(cs_frameSkip);
g_framesToSkip = framesToSkip; g_framesToSkip = framesToSkip;
g_frameSkipCounter = 0; g_frameSkipCounter = 0;
@ -104,8 +104,6 @@ void SetFrameSkipping(unsigned int framesToSkip)
// as this won't be changed anymore when frameskip is turned off // as this won't be changed anymore when frameskip is turned off
if (framesToSkip == 0) if (framesToSkip == 0)
g_video_backend->Video_SetRendering(true); g_video_backend->Video_SetRendering(true);
cs_frameSkip.Leave();
} }
int FrameSkippingFactor() int FrameSkippingFactor()
@ -138,15 +136,13 @@ void FrameSkipping()
// Frameskipping will desync movie playback // Frameskipping will desync movie playback
if (!IsPlayingInput() && !IsRecordingInput()) if (!IsPlayingInput() && !IsRecordingInput())
{ {
cs_frameSkip.Enter(); std::lock_guard<std::mutex> lk(cs_frameSkip);
g_frameSkipCounter++; g_frameSkipCounter++;
if (g_frameSkipCounter > g_framesToSkip || Core::report_slow(g_frameSkipCounter) == false) if (g_frameSkipCounter > g_framesToSkip || Core::report_slow(g_frameSkipCounter) == false)
g_frameSkipCounter = 0; g_frameSkipCounter = 0;
g_video_backend->Video_SetRendering(!g_frameSkipCounter); g_video_backend->Video_SetRendering(!g_frameSkipCounter);
cs_frameSkip.Leave();
} }
} }

View file

@ -121,8 +121,6 @@ CCodeWindow::CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter
sizerLeft->Fit(this); sizerLeft->Fit(this);
sizerBig->Fit(this); sizerBig->Fit(this);
sync_event.Init();
} }
wxMenuBar *CCodeWindow::GetMenuBar() wxMenuBar *CCodeWindow::GetMenuBar()

View file

@ -354,8 +354,6 @@ CFrame::CFrame(wxFrame* parent,
bFloatWindow[i] = false; bFloatWindow[i] = false;
#ifdef __WXGTK__ #ifdef __WXGTK__
panic_event.Init();
keystate_event.Init();
bKeyStateResult = false; bKeyStateResult = false;
#endif #endif
@ -492,11 +490,6 @@ CFrame::~CFrame()
ClosePages(); ClosePages();
#ifdef __WXGTK__
panic_event.Shutdown();
keystate_event.Shutdown();
#endif
delete m_Mgr; delete m_Mgr;
} }

View file

@ -278,9 +278,8 @@ void GamepadPage::ClearAll(wxCommandEvent&)
// no point in using the real ControllerInterface i guess // no point in using the real ControllerInterface i guess
ControllerInterface face; ControllerInterface face;
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(face); controller->UpdateReferences(face);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -289,9 +288,8 @@ void GamepadPage::LoadDefaults(wxCommandEvent&)
{ {
controller->LoadDefaults(g_controller_interface); controller->LoadDefaults(g_controller_interface);
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -300,9 +298,8 @@ void ControlDialog::SetControl(wxCommandEvent&)
{ {
control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue()); control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue());
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -318,9 +315,8 @@ void GamepadPage::SetDevice(wxCommandEvent&)
controller->UpdateDefaultDevice(); controller->UpdateDefaultDevice();
// update references // update references
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
} }
void ControlDialog::SetDevice(wxCommandEvent&) void ControlDialog::SetDevice(wxCommandEvent&)
@ -338,9 +334,8 @@ void ControlDialog::ClearControl(wxCommandEvent&)
{ {
control_reference->expression.clear(); control_reference->expression.clear();
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -363,9 +358,8 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&)
control_reference->expression = STR_FROM_WXSTR(expr); control_reference->expression = STR_FROM_WXSTR(expr);
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -395,25 +389,22 @@ void ControlDialog::AppendControl(wxCommandEvent& event)
control_reference->expression = STR_FROM_WXSTR(expr); control_reference->expression = STR_FROM_WXSTR(expr);
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
void GamepadPage::AdjustSetting(wxCommandEvent& event) void GamepadPage::AdjustSetting(wxCommandEvent& event)
{ {
m_plugin.controls_crit.Enter(); // enter / prolly fine not being here std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue(); ((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue();
m_plugin.controls_crit.Leave(); // leave
} }
void GamepadPage::AdjustControlOption(wxCommandEvent&) void GamepadPage::AdjustControlOption(wxCommandEvent&)
{ {
m_plugin.controls_crit.Enter(); // enter / prolly fine not being here std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
m_control_dialog->control_reference->range = (ControlState)(m_control_dialog->range_slider->GetValue()) / SLIDER_TICK_COUNT; m_control_dialog->control_reference->range = (ControlState)(m_control_dialog->range_slider->GetValue()) / SLIDER_TICK_COUNT;
m_plugin.controls_crit.Leave(); // leave
} }
void GamepadPage::ConfigControl(wxCommandEvent& event) void GamepadPage::ConfigControl(wxCommandEvent& event)
@ -432,9 +423,8 @@ void GamepadPage::ClearControl(wxCommandEvent& event)
btn->control_reference->expression.clear(); btn->control_reference->expression.clear();
btn->control_reference->range = 1.0f; btn->control_reference->range = 1.0f;
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
// update changes // update changes
UpdateGUI(); UpdateGUI();
@ -453,9 +443,8 @@ void ControlDialog::DetectControl(wxCommandEvent& event)
// apparently, this makes the "waiting" text work on Linux // apparently, this makes the "waiting" text work on Linux
wxTheApp->Yield(); wxTheApp->Yield();
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
ControllerInterface::Device::Control* const ctrl = control_reference->Detect(DETECT_WAIT_TIME, dev); ControllerInterface::Device::Control* const ctrl = control_reference->Detect(DETECT_WAIT_TIME, dev);
m_plugin.controls_crit.Leave(); // leave
// if we got input, select it in the list // if we got input, select it in the list
if (ctrl) if (ctrl)
@ -478,7 +467,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event)
// apparently, this makes the "waiting" text work on Linux // apparently, this makes the "waiting" text work on Linux
wxTheApp->Yield(); wxTheApp->Yield();
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
ControllerInterface::Device::Control* const ctrl = btn->control_reference->Detect(DETECT_WAIT_TIME, dev); ControllerInterface::Device::Control* const ctrl = btn->control_reference->Detect(DETECT_WAIT_TIME, dev);
// if we got input, update expression and reference // if we got input, update expression and reference
@ -488,8 +477,6 @@ void GamepadPage::DetectControl(wxCommandEvent& event)
g_controller_interface.UpdateReference(btn->control_reference, controller->default_device); g_controller_interface.UpdateReference(btn->control_reference, controller->default_device);
} }
m_plugin.controls_crit.Leave(); // leave
btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression)); btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression));
} }
} }
@ -597,10 +584,9 @@ void GamepadPage::LoadProfile(wxCommandEvent&)
IniFile inifile; IniFile inifile;
inifile.Load(fname); inifile.Load(fname);
m_plugin.controls_crit.Enter(); std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->LoadConfig(inifile.GetOrCreateSection("Profile")); controller->LoadConfig(inifile.GetOrCreateSection("Profile"));
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave();
UpdateGUI(); UpdateGUI();
} }
@ -662,7 +648,7 @@ void InputConfigDialog::UpdateDeviceComboBox()
void GamepadPage::RefreshDevices(wxCommandEvent&) void GamepadPage::RefreshDevices(wxCommandEvent&)
{ {
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
// refresh devices // refresh devices
g_controller_interface.Shutdown(); g_controller_interface.Shutdown();
@ -673,8 +659,6 @@ void GamepadPage::RefreshDevices(wxCommandEvent&)
// update device cbox // update device cbox
m_config_dialog->UpdateDeviceComboBox(); m_config_dialog->UpdateDeviceComboBox();
m_plugin.controls_crit.Leave(); // leave
} }
ControlGroupBox::~ControlGroupBox() ControlGroupBox::~ControlGroupBox()

View file

@ -22,8 +22,10 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD); wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
g_controller_interface.UpdateInput(); g_controller_interface.UpdateInput();
// don't want game thread updating input when we are using it here // don't want game thread updating input when we are using it here
if (false == g_controller_interface.update_lock.TryEnter()) std::unique_lock<std::mutex> lk(g_controller_interface.update_lock, std::try_to_lock);
if (!lk.owns_lock())
return; return;
GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection()); GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection());
@ -344,6 +346,4 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
(*g)->static_bitmap->SetBitmap(bitmap); (*g)->static_bitmap->SetBitmap(bitmap);
} }
} }
g_controller_interface.update_lock.Leave();
} }

View file

@ -42,7 +42,6 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos,
, x(0), y(0), winpos(0) , x(0), y(0), winpos(0)
, Parent(parent) , m_LogAccess(true) , Parent(parent) , m_LogAccess(true)
, m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL) , m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL)
, m_LogSection(1)
, m_SJISConv(wxT("")) , m_SJISConv(wxT(""))
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -212,11 +211,12 @@ void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event))
{ {
m_Log->Clear(); m_Log->Clear();
m_LogSection.Enter(); {
std::lock_guard<std::mutex> lk(m_LogSection);
int msgQueueSize = (int)msgQueue.size(); int msgQueueSize = (int)msgQueue.size();
for (int i = 0; i < msgQueueSize; i++) for (int i = 0; i < msgQueueSize; i++)
msgQueue.pop(); msgQueue.pop();
m_LogSection.Leave(); }
m_LogManager->getConsoleListener()->ClearScreen(); m_LogManager->getConsoleListener()->ClearScreen();
} }
@ -308,7 +308,8 @@ void CLogWindow::UpdateLog()
m_LogTimer->Stop(); m_LogTimer->Stop();
m_LogSection.Enter(); {
std::lock_guard<std::mutex> lk(m_LogSection);
int msgQueueSize = (int)msgQueue.size(); int msgQueueSize = (int)msgQueue.size();
for (int i = 0; i < msgQueueSize; i++) for (int i = 0; i < msgQueueSize; i++)
{ {
@ -348,16 +349,16 @@ void CLogWindow::UpdateLog()
} }
msgQueue.pop(); msgQueue.pop();
} }
m_LogSection.Leave(); } // unlock log
m_LogTimer->Start(UPDATETIME); m_LogTimer->Start(UPDATETIME);
} }
void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text) void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text)
{ {
m_LogSection.Enter(); std::lock_guard<std::mutex> lk(m_LogSection);
if (msgQueue.size() >= 100) if (msgQueue.size() >= 100)
msgQueue.pop(); msgQueue.pop();
msgQueue.push(std::pair<u8, wxString>((u8)level, wxString(text, m_SJISConv))); msgQueue.push(std::pair<u8, wxString>((u8)level, wxString(text, m_SJISConv)));
m_LogSection.Leave();
} }

View file

@ -72,7 +72,7 @@ private:
wxChoice *m_FontChoice; wxChoice *m_FontChoice;
wxCheckBox *m_WrapLine; wxCheckBox *m_WrapLine;
Common::CriticalSection m_LogSection; std::mutex m_LogSection;
wxCSConv m_SJISConv; wxCSConv m_SJISConv;

View file

@ -118,9 +118,11 @@ void ControllerInterface::SetHwnd( void* const hwnd )
// //
bool ControllerInterface::UpdateInput(const bool force) bool ControllerInterface::UpdateInput(const bool force)
{ {
std::unique_lock<std::mutex> lk(update_lock, std::defer_lock);
if (force) if (force)
update_lock.Enter(); lk.lock();
else if (false == update_lock.TryEnter()) else if (!lk.try_lock())
return false; return false;
size_t ok_count = 0; size_t ok_count = 0;
@ -137,7 +139,6 @@ bool ControllerInterface::UpdateInput(const bool force)
//(*d)->ClearInputState(); //(*d)->ClearInputState();
} }
update_lock.Leave();
return (m_devices.size() == ok_count); return (m_devices.size() == ok_count);
} }
@ -148,9 +149,11 @@ bool ControllerInterface::UpdateInput(const bool force)
// //
bool ControllerInterface::UpdateOutput(const bool force) bool ControllerInterface::UpdateOutput(const bool force)
{ {
std::unique_lock<std::mutex> lk(update_lock, std::defer_lock);
if (force) if (force)
update_lock.Enter(); lk.lock();
else if (false == update_lock.TryEnter()) else if (!lk.try_lock())
return false; return false;
size_t ok_count = 0; size_t ok_count = 0;
@ -161,7 +164,6 @@ bool ControllerInterface::UpdateOutput(const bool force)
for (;d != e; ++d) for (;d != e; ++d)
(*d)->UpdateOutput(); (*d)->UpdateOutput();
update_lock.Leave();
return (m_devices.size() == ok_count); return (m_devices.size() == ok_count);
} }
@ -470,8 +472,8 @@ void ControllerInterface::UpdateReference(ControllerInterface::ControlReference*
else if ('`' == c) else if ('`' == c)
{ {
// different device // different device
if (false == /*XXX*/(bool)std::getline(ss, dev_str, '`')) if (std::getline(ss, dev_str, '`').eof())
break; break; // no terminating '`' character
} }
else else
ctrl_str += c; ctrl_str += c;

View file

@ -222,7 +222,7 @@ public:
const std::vector<Device*>& Devices() const { return m_devices; } const std::vector<Device*>& Devices() const { return m_devices; }
Device* FindDevice(const DeviceQualifier& devq) const; Device* FindDevice(const DeviceQualifier& devq) const;
Common::CriticalSection update_lock; std::mutex update_lock;
private: private:
bool m_is_init; bool m_is_init;

View file

@ -47,7 +47,7 @@ public:
std::vector< ControllerEmu* > controllers; std::vector< ControllerEmu* > controllers;
Common::CriticalSection controls_crit; // critical section for changing any control references std::mutex controls_lock; // for changing any control references
const char * const ini_name; const char * const ini_name;
const char * const gui_name; const char * const gui_name;

View file

@ -52,7 +52,7 @@ struct UDPWiimote::_d
{ {
std::thread thread; std::thread thread;
std::list<sock_t> sockfds; std::list<sock_t> sockfds;
Common::CriticalSection termLock,mutex,nameMutex; std::mutex termLock, mutex, nameMutex;
volatile bool exit; volatile bool exit;
sock_t bipv4_fd, bipv6_fd; sock_t bipv4_fd, bipv6_fd;
}; };
@ -132,15 +132,17 @@ UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) :
d->exit=false; d->exit=false;
initBroadcastIPv4(); initBroadcastIPv4();
initBroadcastIPv6(); initBroadcastIPv6();
d->termLock.Enter();
std::lock_guard<std::mutex> lk(d->termLock);
d->thread = std::thread(std::mem_fun(&UDPWiimote::mainThread), this); d->thread = std::thread(std::mem_fun(&UDPWiimote::mainThread), this);
d->termLock.Leave();
return; return;
} }
void UDPWiimote::mainThread() void UDPWiimote::mainThread()
{ {
d->termLock.Enter(); std::unique_lock<std::mutex> lk(d->termLock);
Common::Timer time; Common::Timer time;
fd_set fds; fd_set fds;
struct timeval timeout; struct timeval timeout;
@ -174,11 +176,11 @@ void UDPWiimote::mainThread()
timeout.tv_usec=(tleft%1000)*1000; timeout.tv_usec=(tleft%1000)*1000;
} }
d->termLock.Leave(); //VERY hacky. don't like it lk.unlock(); //VERY hacky. don't like it
if (d->exit) return; if (d->exit) return;
int rt=select(maxfd,&fds,NULL,NULL,&timeout); int rt=select(maxfd,&fds,NULL,NULL,&timeout);
if (d->exit) return; if (d->exit) return;
d->termLock.Enter(); lk.lock();
if (d->exit) return; if (d->exit) return;
if (rt) if (rt)
@ -200,27 +202,26 @@ void UDPWiimote::mainThread()
} }
else else
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lkm(d->mutex);
if (pharsePacket(bf,size)==0) if (pharsePacket(bf,size)==0)
{ {
//NOTICE_LOG(WIIMOTE,"UDPWII New pack"); //NOTICE_LOG(WIIMOTE,"UDPWII New pack");
} else { } else {
//NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring"); //NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring");
} }
d->mutex.Leave();
} }
} }
} }
} while (!(d->exit)); } while (!(d->exit));
d->termLock.Leave();
} }
UDPWiimote::~UDPWiimote() UDPWiimote::~UDPWiimote()
{ {
d->exit = true; d->exit = true;
{
std::lock_guard<std::mutex> lk(d->termLock);
d->thread.join(); d->thread.join();
d->termLock.Enter(); }
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++)
close(*i); close(*i);
close(d->bipv4_fd); close(d->bipv4_fd);
@ -289,7 +290,6 @@ int UDPWiimote::pharsePacket(u8 * bf, size_t size)
return 0; return 0;
} }
void UDPWiimote::initBroadcastIPv4() void UDPWiimote::initBroadcastIPv4()
{ {
d->bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0); d->bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0);
@ -342,71 +342,64 @@ void UDPWiimote::broadcastPresence()
*((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID *((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID
bf[3]=(u8)index; //wiimote index bf[3]=(u8)index; //wiimote index
*((u16*)(&(bf[4])))=htons(int_port); //port *((u16*)(&(bf[4])))=htons(int_port); //port
d->nameMutex.Enter(); {
std::lock_guard<std::mutex> lk(d->nameMutex);
slen=displayName.size(); slen=displayName.size();
if (slen>=256) if (slen>=256)
slen=255; slen=255;
bf[6]=(u8)slen; //display name size (max 255) bf[6]=(u8)slen; //display name size (max 255)
memcpy(&(bf[7]),displayName.c_str(),slen); //display name memcpy(&(bf[7]),displayName.c_str(),slen); //display name
d->nameMutex.Leave(); }
broadcastIPv4(bf,7+slen); broadcastIPv4(bf,7+slen);
broadcastIPv6(bf,7+slen); broadcastIPv6(bf,7+slen);
} }
void UDPWiimote::getAccel(float &_x, float &_y, float &_z) void UDPWiimote::getAccel(float &_x, float &_y, float &_z)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)x; _x=(float)x;
_y=(float)y; _y=(float)y;
_z=(float)z; _z=(float)z;
d->mutex.Leave();
} }
u32 UDPWiimote::getButtons() u32 UDPWiimote::getButtons()
{ {
u32 msk; u32 msk;
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
msk=mask; msk=mask;
d->mutex.Leave();
return msk; return msk;
} }
void UDPWiimote::getIR(float &_x, float &_y) void UDPWiimote::getIR(float &_x, float &_y)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)pointerX; _x=(float)pointerX;
_y=(float)pointerY; _y=(float)pointerY;
d->mutex.Leave();
} }
void UDPWiimote::getNunchuck(float &_x, float &_y, u8 &_mask) void UDPWiimote::getNunchuck(float &_x, float &_y, u8 &_mask)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)nunX; _x=(float)nunX;
_y=(float)nunY; _y=(float)nunY;
_mask=nunMask; _mask=nunMask;
d->mutex.Leave();
} }
void UDPWiimote::getNunchuckAccel(float &_x, float &_y, float &_z) void UDPWiimote::getNunchuckAccel(float &_x, float &_y, float &_z)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)naX; _x=(float)naX;
_y=(float)naY; _y=(float)naY;
_z=(float)naZ; _z=(float)naZ;
d->mutex.Leave();
} }
const char * UDPWiimote::getPort() const char * UDPWiimote::getPort()
{ {
return port.c_str(); return port.c_str();
} }
void UDPWiimote::changeName(const char * name) void UDPWiimote::changeName(const char * name)
{ {
d->nameMutex.Enter(); std::lock_guard<std::mutex> lk(d->nameMutex);
displayName=name; displayName=name;
d->nameMutex.Leave();
} }

View file

@ -46,7 +46,7 @@ int OSDChoice, OSDTime;
Renderer *g_renderer = NULL; Renderer *g_renderer = NULL;
bool s_bLastFrameDumped = false; bool s_bLastFrameDumped = false;
Common::CriticalSection Renderer::s_criticalScreenshot; std::mutex Renderer::s_criticalScreenshot;
std::string Renderer::s_sScreenshotName; std::string Renderer::s_sScreenshotName;
volatile bool Renderer::s_bScreenshot; volatile bool Renderer::s_bScreenshot;
@ -182,10 +182,9 @@ bool Renderer::CalculateTargetSize(int multiplier)
void Renderer::SetScreenshot(const char *filename) void Renderer::SetScreenshot(const char *filename)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
s_sScreenshotName = filename; s_sScreenshotName = filename;
s_bScreenshot = true; s_bScreenshot = true;
s_criticalScreenshot.Leave();
} }
// Create On-Screen-Messages // Create On-Screen-Messages

View file

@ -142,7 +142,7 @@ public:
protected: protected:
static Common::CriticalSection s_criticalScreenshot; static std::mutex s_criticalScreenshot;
static std::string s_sScreenshotName; static std::string s_sScreenshotName;
static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY); static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY);

View file

@ -1094,10 +1094,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Save screenshot // Save screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
SaveScreenshot(s_sScreenshotName, dst_rect); SaveScreenshot(s_sScreenshotName, dst_rect);
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave();
} }
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {

View file

@ -1150,19 +1150,18 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Save screenshot // Save screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
SaveScreenshot(s_sScreenshotName, dst_rect); SaveScreenshot(s_sScreenshotName, dst_rect);
// Reset settings // Reset settings
s_sScreenshotName.clear(); s_sScreenshotName.clear();
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave();
} }
// Frame dumps are handled a little differently in Windows // Frame dumps are handled a little differently in Windows
#if defined _WIN32 || defined HAVE_LIBAV #if defined _WIN32 || defined HAVE_LIBAV
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
if (!data || w != dst_rect.GetWidth() || if (!data || w != dst_rect.GetWidth() ||
h != dst_rect.GetHeight()) h != dst_rect.GetHeight())
{ {
@ -1205,8 +1204,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
} }
else else
NOTICE_LOG(VIDEO, "Error reading framebuffer"); NOTICE_LOG(VIDEO, "Error reading framebuffer");
s_criticalScreenshot.Leave();
} }
else else
{ {

View file

@ -70,8 +70,6 @@ volatile bool interruptWaiting;
CPReg cpreg; // shared between gfx and emulator thread CPReg cpreg; // shared between gfx and emulator thread
Common::CriticalSection criticalSection;
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
{ {
p.Do(cpreg); p.Do(cpreg);