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:
parent
a037ff2358
commit
423018f811
|
@ -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();
|
||||
}
|
||||
|
@ -58,8 +60,6 @@ void AOSound::SoundLoop()
|
|||
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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class DSound : public SoundStream
|
|||
{
|
||||
#ifdef _WIN32
|
||||
std::thread thread;
|
||||
Common::EventEx soundSyncEvent;
|
||||
Common::Event soundSyncEvent;
|
||||
void *hWnd;
|
||||
|
||||
IDirectSound8* ds;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class XAudio2 : public SoundStream
|
|||
IXAudio2MasteringVoice *pMasteringVoice;
|
||||
IXAudio2SourceVoice *pSourceVoice;
|
||||
|
||||
Common::EventEx soundSyncEvent;
|
||||
Common::Event soundSyncEvent;
|
||||
float m_volume;
|
||||
|
||||
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -55,219 +55,49 @@ void SetCurrentThreadAffinity(u32 mask)
|
|||
SetThreadAffinityMask(GetCurrentThread(), mask);
|
||||
}
|
||||
|
||||
CriticalSection::CriticalSection(int spincount)
|
||||
{
|
||||
if (spincount)
|
||||
{
|
||||
if (!InitializeCriticalSectionAndSpinCount(§ion, spincount))
|
||||
ERROR_LOG(COMMON, "CriticalSection could not be initialized!\n%s", GetLastErrorMsg());
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeCriticalSection(§ion);
|
||||
}
|
||||
}
|
||||
// Supporting functions
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
CriticalSection::~CriticalSection()
|
||||
{
|
||||
DeleteCriticalSection(§ion);
|
||||
}
|
||||
|
||||
void CriticalSection::Enter()
|
||||
{
|
||||
EnterCriticalSection(§ion);
|
||||
}
|
||||
|
||||
bool CriticalSection::TryEnter()
|
||||
{
|
||||
return TryEnterCriticalSection(§ion) ? true : false;
|
||||
}
|
||||
|
||||
void CriticalSection::Leave()
|
||||
{
|
||||
LeaveCriticalSection(§ion);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SwitchCurrentThread()
|
||||
{
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
// Supporting functions
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
// 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
|
||||
|
||||
void SwitchCurrentThread()
|
||||
{
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
// 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
|
||||
|
||||
// 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)
|
||||
} info;
|
||||
#pragma pack(pop)
|
||||
|
||||
info.dwType = 0x1000;
|
||||
info.szName = szThreadName;
|
||||
info.dwThreadID = -1; //dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
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);
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{}
|
||||
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,151 +123,42 @@ void SetCurrentThreadAffinity(u32 mask)
|
|||
SetThreadAffinity(pthread_self(), mask);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
static pthread_key_t threadname_key;
|
||||
static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
usleep(1000 * ms);
|
||||
}
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
usleep(1000 * ms);
|
||||
}
|
||||
|
||||
void SwitchCurrentThread()
|
||||
{
|
||||
usleep(1000 * 1);
|
||||
}
|
||||
void SwitchCurrentThread()
|
||||
{
|
||||
usleep(1000 * 1);
|
||||
}
|
||||
|
||||
static void FreeThreadName(void* threadname)
|
||||
{
|
||||
static void FreeThreadName(void* threadname)
|
||||
{
|
||||
free(threadname);
|
||||
}
|
||||
|
||||
static void ThreadnameKeyAlloc()
|
||||
{
|
||||
pthread_key_create(&threadname_key, FreeThreadName);
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char* szThreadName)
|
||||
{
|
||||
pthread_once(&threadname_key_once, ThreadnameKeyAlloc);
|
||||
|
||||
void* threadname;
|
||||
if ((threadname = pthread_getspecific(threadname_key)) != NULL)
|
||||
free(threadname);
|
||||
}
|
||||
|
||||
static void ThreadnameKeyAlloc()
|
||||
{
|
||||
pthread_key_create(&threadname_key, FreeThreadName);
|
||||
}
|
||||
pthread_setspecific(threadname_key, strdup(szThreadName));
|
||||
|
||||
void SetCurrentThreadName(const TCHAR* szThreadName)
|
||||
{
|
||||
pthread_once(&threadname_key_once, ThreadnameKeyAlloc);
|
||||
INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName);
|
||||
}
|
||||
|
||||
void* threadname;
|
||||
if ((threadname = pthread_getspecific(threadname_key)) != NULL)
|
||||
free(threadname);
|
||||
|
||||
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
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,24 +149,23 @@ bool RunGeckoCode(GeckoCode& gecko_code)
|
|||
|
||||
bool RunActiveCodes()
|
||||
{
|
||||
if (false == SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
|
||||
return true;
|
||||
if (false == active_codes_lock.TryEnter())
|
||||
return true;
|
||||
|
||||
std::vector<GeckoCode>::iterator
|
||||
gcodes_iter = active_codes.begin(),
|
||||
gcodes_end = active_codes.end();
|
||||
for (; gcodes_iter!=gcodes_end; ++gcodes_iter)
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
|
||||
{
|
||||
if (gcodes_iter->enabled)
|
||||
RunGeckoCode(*gcodes_iter);
|
||||
// we don't need to stop all codes if one fails, maybe
|
||||
//if (false == RunGeckoCode(*gcodes_iter))
|
||||
//return false;
|
||||
std::lock_guard<std::mutex> lk(active_codes_lock);
|
||||
|
||||
std::vector<GeckoCode>::iterator
|
||||
gcodes_iter = active_codes.begin(),
|
||||
gcodes_end = active_codes.end();
|
||||
for (; gcodes_iter!=gcodes_end; ++gcodes_iter)
|
||||
{
|
||||
if (gcodes_iter->enabled)
|
||||
RunGeckoCode(*gcodes_iter);
|
||||
// we don't need to stop all codes if one fails, maybe
|
||||
//if (false == RunGeckoCode(*gcodes_iter))
|
||||
//return false;
|
||||
}
|
||||
}
|
||||
|
||||
active_codes_lock.Leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ protected:
|
|||
bool NeedsResumeMail();
|
||||
|
||||
CMailHandler& m_rMailHandler;
|
||||
Common::CriticalSection m_csMix;
|
||||
std::mutex m_csMix;
|
||||
|
||||
enum EDSP_Codes
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -123,8 +122,10 @@ void GeckoSockServer::ClientThread()
|
|||
{
|
||||
u8 data;
|
||||
std::size_t got = 0;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(transfer_lock);
|
||||
|
||||
transfer_lock.Enter();
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
//{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,10 +109,11 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,8 +121,6 @@ CCodeWindow::CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter
|
|||
|
||||
sizerLeft->Fit(this);
|
||||
sizerBig->Fit(this);
|
||||
|
||||
sync_event.Init();
|
||||
}
|
||||
|
||||
wxMenuBar *CCodeWindow::GetMenuBar()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ private:
|
|||
wxChoice *m_FontChoice;
|
||||
wxCheckBox *m_WrapLine;
|
||||
|
||||
Common::CriticalSection m_LogSection;
|
||||
std::mutex m_LogSection;
|
||||
|
||||
wxCSConv m_SJISConv;
|
||||
|
||||
|
|
|
@ -118,10 +118,12 @@ 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())
|
||||
return false;
|
||||
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,10 +149,12 @@ 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())
|
||||
return false;
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue