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
parent a037ff2358
commit 423018f811
56 changed files with 918 additions and 835 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -255,6 +255,8 @@
<ClInclude Include="Src\SDCardUtil.h" />
<ClInclude Include="Src\Setup.h" />
<ClInclude Include="Src\stdafx.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdThread.h" />
<ClInclude Include="Src\StringUtil.h" />
<ClInclude Include="Src\svnrev.h" />

View File

@ -121,6 +121,8 @@
<ClInclude Include="Src\Crypto\tools.h">
<Filter>Crypto</Filter>
</ClInclude>
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
</ItemGroup>
<ItemGroup>
<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() {
logMutex = new Common::CriticalSection(1);
LogManager::LogManager()
{
// create log files
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
@ -105,7 +104,6 @@ LogManager::~LogManager() {
delete m_fileLog;
delete m_consoleLog;
delete logMutex;
}
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],
log->getShortName(), temp);
logMutex->Enter();
std::lock_guard<std::mutex> lk(logMutex);
log->trigger(level, msg);
logMutex->Leave();
}
void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener) {
logMutex->Enter();
void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener)
{
std::lock_guard<std::mutex> lk(logMutex);
m_Log[type]->removeListener(listener);
logMutex->Leave();
}
void LogManager::Init()

View File

@ -20,6 +20,7 @@
#include "Log.h"
#include "StringUtil.h"
#include "Thread.h"
#include <vector>
#include <string.h>
@ -102,16 +103,11 @@ private:
class ConsoleListener;
// Avoid <windows.h> include through Thread.h
namespace Common {
class CriticalSection;
}
class LogManager : NonCopyable
{
private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
Common::CriticalSection *logMutex;
std::mutex logMutex;
FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog;
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,219 +55,49 @@ void SetCurrentThreadAffinity(u32 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
void SleepCurrentThread(int ms)
{
// Supporting functions
void SleepCurrentThread(int ms)
{
Sleep(ms);
}
}
void SwitchCurrentThread()
{
void SwitchCurrentThread()
{
SwitchToThread();
}
}
typedef struct tagTHREADNAME_INFO
// Sets the debugger-visible name of the current thread.
// Uses undocumented (actually, it is now documented) trick.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
// This is implemented much nicer in upcoming msvc++, see:
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
void SetCurrentThreadName(const char* szThreadName)
{
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
} THREADNAME_INFO;
// Usage: SetThreadName (-1, "MainThread");
//
// Sets the debugger-visible name of the current thread.
// Uses undocumented (actually, it is now documented) trick.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
} info;
#pragma pack(pop)
// This is implemented much nicer in upcoming msvc++, see:
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
void SetCurrentThreadName(const TCHAR* szThreadName)
{
THREADNAME_INFO info;
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;
#endif
info.dwThreadID = -1; //dwThreadID;
info.dwFlags = 0;
__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)
{}
}
}
#else // !WIN32, so must be POSIX threads
@ -293,72 +123,31 @@ void SetCurrentThreadAffinity(u32 mask)
SetThreadAffinity(pthread_self(), mask);
}
static pthread_key_t threadname_key;
static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT;
static pthread_key_t threadname_key;
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);
}
}
void SwitchCurrentThread()
{
void SwitchCurrentThread()
{
usleep(1000 * 1);
}
}
static void FreeThreadName(void* threadname)
{
static void FreeThreadName(void* threadname)
{
free(threadname);
}
}
static void ThreadnameKeyAlloc()
{
static void ThreadnameKeyAlloc()
{
pthread_key_create(&threadname_key, FreeThreadName);
}
}
void SetCurrentThreadName(const TCHAR* szThreadName)
{
void SetCurrentThreadName(const char* szThreadName)
{
pthread_once(&threadname_key_once, ThreadnameKeyAlloc);
void* threadname;
@ -368,75 +157,7 @@ void SetCurrentThreadAffinity(u32 mask)
pthread_setspecific(threadname_key, strdup(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

View File

@ -19,6 +19,8 @@
#define _THREAD_H_
#include "StdThread.h"
#include "StdMutex.h"
#include "StdConditionVariable.h"
// Don't include common.h here as it will break LogManager
#include "CommonTypes.h"
@ -38,7 +40,6 @@
#include <sys/time.h>
#endif
namespace Common
{
@ -47,105 +48,70 @@ int CurrentThreadId();
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
void SetCurrentThreadAffinity(u32 mask);
class CriticalSection
class Event
{
public:
void Set()
{
#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
{
public:
Event();
void Init();
void Shutdown();
void Set();
//returns whether the wait timed out
bool Wait(const u32 timeout = INFINITE);
#ifdef _WIN32
void MsgWait();
#else
void MsgWait() {Wait();}
#endif
private:
#ifdef _WIN32
HANDLE m_hEvent;
/* If we have waited more than five seconds we can be pretty sure that the thread is deadlocked.
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
start another game without any noticable problems). But several times it failed to, and ended
with a crash. But it's better than an infinite deadlock. */
static const int THREAD_WAIT_TIMEOUT = 5000; // INFINITE or 5000 for example
#else
bool is_set_;
#ifdef _POSIX_THREADS
pthread_cond_t event_;
pthread_mutex_t mutex_;
#endif
#endif
};
void SleepCurrentThread(int ms);
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
// Use this function during a spin-wait to make the current thread
// relax while another thread is working. This may be more efficient
// than using events because event functions use kernel calls.
inline void YieldCPU()
{
#ifdef _WIN32
Sleep(0);
#elif defined(_M_IX86) || defined(_M_X64)
sleep(0);
#endif
m_condvar.notify_one();
}
void SetCurrentThreadName(const char *name);
void Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
m_condvar.wait(lk);
}
private:
std::condition_variable m_condvar;
std::mutex m_mutex;
};
// TODO: doesn't work on windows with (count > 2)
class Barrier
{
public:
Barrier(size_t count)
: m_count(count), m_waiting(0)
{}
// block until "count" threads call Wait()
bool Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
if (m_count == ++m_waiting)
{
m_waiting = 0;
m_condvar.notify_all();
return true;
}
else
{
m_condvar.wait(lk);
return false;
}
}
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 SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
// Use this function during a spin-wait to make the current thread
// relax while another thread is working. This may be more efficient
// than using events because event functions use kernel calls.
inline void YieldCPU()
{
std::this_thread::yield();
}
void SetCurrentThreadName(const char *name);
} // namespace Common

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -570,7 +570,7 @@ void CUCode_Zelda::ExecuteList()
void CUCode_Zelda::DoState(PointerWrap &p)
{
// 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);
@ -618,6 +618,4 @@ void CUCode_Zelda::DoState(PointerWrap &p)
p.Do(m_UploadSetupInProgress);
m_rMailHandler.DoState(p);
m_csMix.Leave();
}

View File

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

View File

@ -86,7 +86,7 @@ protected:
bool NeedsResumeMail();
CMailHandler& m_rMailHandler;
Common::CriticalSection m_csMix;
std::mutex m_csMix;
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"
// (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 insertDisc;
@ -345,10 +345,8 @@ void ClearCoverInterrupt()
bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength)
{
// We won't need the crit sec when DTK streaming has been rewritten correctly.
dvdread_section.Enter();
bool retval = VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength);
dvdread_section.Leave();
return retval;
std::lock_guard<std::mutex> lk(dvdread_section);
return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength);
}
bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
@ -360,9 +358,10 @@ bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
return false;
}
_iNumSamples &= ~31;
dvdread_section.Enter();
{
std::lock_guard<std::mutex> lk(dvdread_section);
VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples);
dvdread_section.Leave();
}
//
// FIX THIS

View File

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

View File

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

View File

@ -65,8 +65,9 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// wtf is this?
_pPADStatus->button = PAD_USE_ORIGIN;
// try lock
if (false == g_plugin.controls_crit.TryEnter())
std::unique_lock<std::mutex> lk(g_plugin.controls_lock, std::try_to_lock);
if (!lk.owns_lock())
{
// if gui has lock (messing with controls), skip this input cycle
// center axes and return
@ -86,9 +87,6 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// get input
((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)
{
// enter
if ( g_plugin.controls_crit.TryEnter() )
std::unique_lock<std::mutex> lk(g_plugin.controls_lock, std::try_to_lock);
if (!lk.owns_lock())
{
// TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time
// set rumble
((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::queue<sf::SocketTCP> waiting_socks;
static Common::CriticalSection cs_gba;
static std::mutex cs_gba;
namespace { volatile bool server_running; }
// --- GameBoy Advance "Link Cable" ---
@ -47,9 +47,8 @@ void GBAConnectionWaiter()
{
if (server.Accept(new_client) == sf::Socket::Done)
{
cs_gba.Enter();
std::lock_guard<std::mutex> lk(cs_gba);
waiting_socks.push(new_client);
cs_gba.Leave();
}
SLEEP(1);
}
@ -68,14 +67,14 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
{
bool sock_filled = false;
cs_gba.Enter();
std::lock_guard<std::mutex> lk(cs_gba);
if (waiting_socks.size())
{
sock_to_fill = waiting_socks.front();
waiting_socks.pop();
sock_filled = true;
}
cs_gba.Leave();
return sock_filled;
}

View File

@ -93,8 +93,8 @@ void Update(int _number)
{
//PanicAlert( "Wiimote_Update" );
// TODO: change this to a TryEnter, and make it give empty input on failure
g_plugin.controls_crit.Enter();
// TODO: change this to a try_to_lock, and make it give empty input on failure
std::lock_guard<std::mutex> lk(g_plugin.controls_lock);
static int _last_number = 4;
if (_number <= _last_number)
@ -108,8 +108,6 @@ void Update(int _number)
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update();
else
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;
g_refresh_critsec.Enter();
std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index])
{
wm_request_status rpt;
rpt.rumble = 0;
g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
}
g_refresh_critsec.Leave();
return;
}

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@
// for wiimote/ OSD messages
#include "Core.h"
Common::CriticalSection crit_netplay_ptr;
std::mutex crit_netplay_ptr;
static NetPlay* netplay_ptr = NULL;
#define RPT_SIZE_HACK (1 << 16)
@ -42,20 +42,20 @@ NetPlay::NetPlay(NetPlayUI* dialog)
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;
}
void NetPlay_Disable()
{
CritLocker crit(crit_netplay_ptr);
std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = NULL;
}
// called from ---GUI--- thread
NetPlay::~NetPlay()
{
CritLocker crit(crit_netplay_ptr);
std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = NULL;
// not perfect
@ -116,7 +116,8 @@ void NetPlay::ClearBuffers()
// called from ---CPU--- thread
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
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;
//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().channel = _channelID;
}
m_crit.players.Leave();
}
// called from ---CPU--- thread
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
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_crit.players.Leave();
} // unlock players
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)
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)
{
@ -288,7 +288,7 @@ u8 NetPlay::GetPadNum(u8 numPAD)
// Actual Core function which is called on every frame
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)
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
u32 CEXIIPL::NetPlay_GetGCTime()
{
CritLocker crit(crit_netplay_ptr);
std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr)
return 1272737767; // watev
@ -312,7 +312,7 @@ u32 CEXIIPL::NetPlay_GetGCTime()
// return the local pad num that should rumble given a ingame pad num
u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD)
{
CritLocker crit(crit_netplay_ptr);
std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr)
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, u16, const void*, u32&)
{
CritLocker crit(crit_netplay_ptr);
std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr)
//{

View File

@ -75,19 +75,6 @@ enum
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
{
public:
@ -135,9 +122,9 @@ protected:
struct
{
Common::CriticalSection game;
std::recursive_mutex game;
// lock order
Common::CriticalSection players, send;
std::recursive_mutex players, send;
} m_crit;
class Player

View File

@ -93,9 +93,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> player.name;
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_crit.players.Leave();
}
m_dialog->Update();
}
@ -106,9 +107,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
PlayerId 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_crit.players.Leave();
}
m_dialog->Update();
}
@ -137,12 +139,13 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
PlayerId pid;
packet >> pid;
m_crit.players.Enter(); // lock players
{
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
Player& player = m_players[pid];
for (unsigned int i=0; i<4; ++i)
packet >> player.pad_map[i];
m_crit.players.Leave();
}
m_dialog->Update();
}
@ -171,10 +174,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
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;
m_crit.game.Leave();
}
// update gui
m_dialog->OnMsgChangeGame(m_selected_game);
@ -183,9 +186,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
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;
m_crit.game.Leave();
}
m_dialog->OnMsgStartGame();
}
@ -200,7 +204,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_DISABLE_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;
NetPlay_Disable();
}
@ -215,7 +219,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
spac << (MessageId)NP_MSG_PONG;
spac << ping_key;
CritLocker send_lock(m_crit.send);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac);
}
break;
@ -263,7 +267,7 @@ void NetPlayClient::ThreadFunc()
// called from ---GUI--- thread
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;
@ -287,7 +291,7 @@ void NetPlayClient::SendChatMessage(const std::string& msg)
spac << (MessageId)NP_MSG_CHAT_MESSAGE;
spac << msg;
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
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 << 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);
}
// called from ---GUI--- thread
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))
return false;
@ -317,7 +321,7 @@ bool NetPlayClient::StartGame(const std::string &path)
spac << (MessageId)NP_MSG_START_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);
return true;

View File

@ -60,8 +60,7 @@ void NetPlayServer::ThreadFunc()
spac << (MessageId)NP_MSG_PING;
spac << m_ping_key;
//CritLocker player_lock(m_crit.players);
CritLocker send_lock(m_crit.send);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_ping_timer.Start();
SendToClients(spac);
@ -80,9 +79,11 @@ void NetPlayServer::ThreadFunc()
sf::SocketTCP accept_socket;
m_socket.Accept(accept_socket);
m_crit.game.Enter(); // lock game state
const unsigned int error = OnConnect(accept_socket);
m_crit.game.Leave();
unsigned int error;
{
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
error = OnConnect(accept_socket);
}
if (error)
{
@ -108,14 +109,15 @@ void NetPlayServer::ThreadFunc()
//case sf::Socket::Disconnected :
default :
m_crit.game.Enter(); // lock game state
{
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
OnDisconnect(ready_socket);
m_crit.game.Leave();
break;
}
}
}
}
}
// 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
sf::Packet spac;
@ -230,16 +232,16 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
socket.Send(spac);
}
// LEAVE
m_crit.send.Leave();
} // unlock send
// 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_crit.send.Enter(); // lock send
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone
m_crit.send.Leave();
m_crit.players.Leave();
}
// add client to selector/ used for receiving
m_selector.Add(socket);
@ -255,14 +257,14 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
if (m_is_running)
{
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;
NetPlay_Disable();
sf::Packet spac;
spac << (MessageId)NP_MSG_DISABLE_GAME;
// 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);
}
@ -272,11 +274,11 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& 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));
// 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);
m_dialog->Update();
@ -287,7 +289,7 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
// called from ---GUI--- thread
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
i = m_players.begin(),
e = m_players.end();
@ -309,11 +311,11 @@ bool NetPlayServer::GetPadMapping(const int pid, int map[])
// called from ---GUI--- thread
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)
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
i = m_players.begin(),
e = m_players.end();
@ -340,7 +342,7 @@ bool NetPlayServer::SetPadMapping(const int pid, const int map[])
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
m_dialog->Update();
@ -369,7 +371,7 @@ void NetPlayServer::UpdatePadMapping()
// called from ---GUI--- thread and ---NETPLAY--- thread
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
i = m_players.begin(),
@ -392,7 +394,7 @@ u64 NetPlayServer::CalculateMinimumBufferTime()
// called from ---GUI--- thread and ---NETPLAY--- thread
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;
@ -401,8 +403,8 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size)
spac << (MessageId)NP_MSG_PAD_BUFFER;
spac << (u32)m_target_buffer_size;
CritLocker player_lock(m_crit.players); // lock players
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
}
@ -429,9 +431,10 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
spac << player.pid;
spac << msg;
m_crit.send.Enter(); // lock send
{
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid);
m_crit.send.Leave();
}
// add to gui
std::ostringstream ss;
@ -471,7 +474,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
spac << map; // in game mapping
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);
}
break;
@ -510,7 +513,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
// called from ---GUI--- thread
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;
@ -534,15 +537,15 @@ void NetPlayServer::SendChatMessage(const std::string& msg)
spac << (PlayerId)0; // server id always 0
spac << msg;
CritLocker player_lock(m_crit.players); // lock players
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
}
// called from ---GUI--- thread
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;
@ -551,8 +554,8 @@ bool NetPlayServer::ChangeGame(const std::string &game)
spac << (MessageId)NP_MSG_CHANGE_GAME;
spac << game;
CritLocker player_lock(m_crit.players); // lock players
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
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 << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
}
// called from ---GUI--- thread
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))
return false;
@ -590,8 +593,8 @@ bool NetPlayServer::StartGame(const std::string &path)
spac << (MessageId)NP_MSG_START_GAME;
spac << m_current_game;
CritLocker player_lock(m_crit.players); // lock players
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
return true;
@ -608,8 +611,8 @@ bool NetPlayServer::StopGame()
sf::Packet spac;
spac << (MessageId)NP_MSG_STOP_GAME;
CritLocker player_lock(m_crit.players); // lock players
CritLocker send_lock(m_crit.send); // lock send
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
return true;

View File

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

View File

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

View File

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

View File

@ -278,9 +278,8 @@ void GamepadPage::ClearAll(wxCommandEvent&)
// no point in using the real ControllerInterface i guess
ControllerInterface face;
m_plugin.controls_crit.Enter(); // enter
std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(face);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI();
}
@ -289,9 +288,8 @@ void GamepadPage::LoadDefaults(wxCommandEvent&)
{
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);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI();
}
@ -300,9 +298,8 @@ void ControlDialog::SetControl(wxCommandEvent&)
{
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);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI();
}
@ -318,9 +315,8 @@ void GamepadPage::SetDevice(wxCommandEvent&)
controller->UpdateDefaultDevice();
// update references
m_plugin.controls_crit.Enter(); // enter
std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
}
void ControlDialog::SetDevice(wxCommandEvent&)
@ -338,9 +334,8 @@ void ControlDialog::ClearControl(wxCommandEvent&)
{
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);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI();
}
@ -363,9 +358,8 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&)
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);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI();
}
@ -395,25 +389,22 @@ void ControlDialog::AppendControl(wxCommandEvent& event)
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);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI();
}
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();
m_plugin.controls_crit.Leave(); // leave
}
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_plugin.controls_crit.Leave(); // leave
}
void GamepadPage::ConfigControl(wxCommandEvent& event)
@ -432,9 +423,8 @@ void GamepadPage::ClearControl(wxCommandEvent& event)
btn->control_reference->expression.clear();
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);
m_plugin.controls_crit.Leave(); // leave
// update changes
UpdateGUI();
@ -453,9 +443,8 @@ void ControlDialog::DetectControl(wxCommandEvent& event)
// apparently, this makes the "waiting" text work on Linux
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);
m_plugin.controls_crit.Leave(); // leave
// if we got input, select it in the list
if (ctrl)
@ -478,7 +467,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event)
// apparently, this makes the "waiting" text work on Linux
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);
// 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);
}
m_plugin.controls_crit.Leave(); // leave
btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression));
}
}
@ -597,10 +584,9 @@ void GamepadPage::LoadProfile(wxCommandEvent&)
IniFile inifile;
inifile.Load(fname);
m_plugin.controls_crit.Enter();
std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->LoadConfig(inifile.GetOrCreateSection("Profile"));
controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave();
UpdateGUI();
}
@ -662,7 +648,7 @@ void InputConfigDialog::UpdateDeviceComboBox()
void GamepadPage::RefreshDevices(wxCommandEvent&)
{
m_plugin.controls_crit.Enter(); // enter
std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
// refresh devices
g_controller_interface.Shutdown();
@ -673,8 +659,6 @@ void GamepadPage::RefreshDevices(wxCommandEvent&)
// update device cbox
m_config_dialog->UpdateDeviceComboBox();
m_plugin.controls_crit.Leave(); // leave
}
ControlGroupBox::~ControlGroupBox()

View File

@ -22,8 +22,10 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
g_controller_interface.UpdateInput();
// 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;
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_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)
, Parent(parent) , m_LogAccess(true)
, m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL)
, m_LogSection(1)
, m_SJISConv(wxT(""))
{
#ifdef _WIN32
@ -212,11 +211,12 @@ void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event))
{
m_Log->Clear();
m_LogSection.Enter();
{
std::lock_guard<std::mutex> lk(m_LogSection);
int msgQueueSize = (int)msgQueue.size();
for (int i = 0; i < msgQueueSize; i++)
msgQueue.pop();
m_LogSection.Leave();
}
m_LogManager->getConsoleListener()->ClearScreen();
}
@ -308,7 +308,8 @@ void CLogWindow::UpdateLog()
m_LogTimer->Stop();
m_LogSection.Enter();
{
std::lock_guard<std::mutex> lk(m_LogSection);
int msgQueueSize = (int)msgQueue.size();
for (int i = 0; i < msgQueueSize; i++)
{
@ -348,16 +349,16 @@ void CLogWindow::UpdateLog()
}
msgQueue.pop();
}
m_LogSection.Leave();
} // unlock log
m_LogTimer->Start(UPDATETIME);
}
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)
msgQueue.pop();
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;
wxCheckBox *m_WrapLine;
Common::CriticalSection m_LogSection;
std::mutex m_LogSection;
wxCSConv m_SJISConv;

View File

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

View File

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

View File

@ -47,7 +47,7 @@ public:
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 gui_name;

View File

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

View File

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

View File

@ -142,7 +142,7 @@ public:
protected:
static Common::CriticalSection s_criticalScreenshot;
static std::mutex s_criticalScreenshot;
static std::string s_sScreenshotName;
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
if (s_bScreenshot)
{
s_criticalScreenshot.Enter();
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
SaveScreenshot(s_sScreenshotName, dst_rect);
s_bScreenshot = false;
s_criticalScreenshot.Leave();
}
if (g_ActiveConfig.bDumpFrames)
{

View File

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

View File

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