diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index e5c94153c5..91be776722 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -233,7 +233,6 @@
-
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 7ef3033764..cc8b91d6ad 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -19,7 +19,6 @@
-
diff --git a/Common/LogManager.cpp b/Common/LogManager.cpp
index 373a76040e..5d7d5da981 100644
--- a/Common/LogManager.cpp
+++ b/Common/LogManager.cpp
@@ -187,7 +187,7 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const
if (level > log->GetLevel() || !log->IsEnabled() || !log->HasListeners())
return;
- std::lock_guard lk(log_lock_);
+ lock_guard lk(log_lock_);
static const char level_to_char[8] = "-NEWIDV";
char formattedTime[13];
Common::Timer::GetTimeFormatted(formattedTime);
@@ -266,13 +266,13 @@ LogChannel::LogChannel(const char* shortName, const char* fullName, bool enable)
// LogContainer
void LogChannel::AddListener(LogListener *listener) {
- std::lock_guard lk(m_listeners_lock);
+ lock_guard lk(m_listeners_lock);
m_listeners.insert(listener);
m_hasListeners = true;
}
void LogChannel::RemoveListener(LogListener *listener) {
- std::lock_guard lk(m_listeners_lock);
+ lock_guard lk(m_listeners_lock);
m_listeners.erase(listener);
m_hasListeners = !m_listeners.empty();
}
@@ -281,7 +281,7 @@ void LogChannel::Trigger(LogTypes::LOG_LEVELS level, const char *msg) {
#ifdef __SYMBIAN32__
RDebug::Printf("%s",msg);
#else
- std::lock_guard lk(m_listeners_lock);
+ lock_guard lk(m_listeners_lock);
std::set::const_iterator i;
for (i = m_listeners.begin(); i != m_listeners.end(); ++i) {
@@ -303,7 +303,7 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) {
if (!IsEnabled() || !IsValid())
return;
- std::lock_guard lk(m_log_lock);
+ lock_guard lk(m_log_lock);
m_logfile << msg << std::flush;
}
diff --git a/Common/LogManager.h b/Common/LogManager.h
index 452ffdf86b..d6a0785718 100644
--- a/Common/LogManager.h
+++ b/Common/LogManager.h
@@ -17,13 +17,12 @@
#pragma once
+#include
+#include "base/mutex.h"
+#include "file/ini_file.h"
#include "Log.h"
#include "StringUtils.h"
#include "FileUtil.h"
-#include "file/ini_file.h"
-
-#include
-#include "StdMutex.h"
#define MAX_MESSAGES 8000
#define MAX_MSGLEN 1024
@@ -51,7 +50,7 @@ public:
const char* GetName() const { return "file"; }
private:
- std::mutex m_log_lock;
+ recursive_mutex m_log_lock;
std::ofstream m_logfile;
bool m_enable;
};
@@ -113,7 +112,7 @@ public:
private:
char m_fullName[128];
char m_shortName[32];
- std::mutex m_listeners_lock;
+ recursive_mutex m_listeners_lock;
std::set m_listeners;
bool m_hasListeners;
};
@@ -128,7 +127,7 @@ private:
DebuggerLogListener *debuggerLog_;
RingbufferLogListener *ringLog_;
static LogManager *logManager_; // Singleton. Ugh.
- std::mutex log_lock_;
+ recursive_mutex log_lock_;
LogManager();
~LogManager();
diff --git a/Common/StdMutex.h b/Common/StdMutex.h
deleted file mode 100644
index d42060e980..0000000000
--- a/Common/StdMutex.h
+++ /dev/null
@@ -1,353 +0,0 @@
-
-#pragma once
-
-#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
-#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-
-// Note: __MAC_10_7 is defined on 10.7+.
-#if (__cplusplus >= 201103L || defined(__APPLE__) \
- || (GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__)) \
-/* GCC 4.4 provides , except on these platforms: */ \
- && !defined(ANDROID) && !defined(__SYMBIAN32__) && !defined(MACGNUSTD)
-#include
-#else
-
-// partial implementation for win32/pthread
-#include
-
-#if defined(_WIN32) // WIN32
-#include "CommonWindows.h"
-#else // POSIX
-#include
-#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_init(&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;
-};
-
-#if !defined(_WIN32) || defined(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
- // XXX TryAcquireSRWLockExclusive requires Windows 7!
- // return (0 != TryAcquireSRWLockExclusive(&m_handle));
- return false;
-#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 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 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
- //unique_lock(mutex_type& m, const chrono::time_point& abs_time);
-
- //template
- //unique_lock(mutex_type& m, const chrono::duration& 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(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(u);
-#endif
- swap(other);
- }
-
- void lock()
- {
- mutex()->lock();
- owns = true;
- }
-
- bool try_lock()
- {
- owns = mutex()->try_lock();
- return owns;
- }
-
- //template
- //bool try_lock_for(const chrono::duration& rel_time);
- //template
- //bool try_lock_until(const chrono::time_point& 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()
- {
- mutex_type* const ret = mutex();
-
- pm = NULL;
- owns = false;
-
- return ret;
- }
-
- 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
-void swap(unique_lock& x, unique_lock& y)
-{
- x.swap(y);
-}
-
-}
-
-#endif
diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp
index 7b25787fdc..42da031ba9 100644
--- a/Core/CoreTiming.cpp
+++ b/Core/CoreTiming.cpp
@@ -20,10 +20,10 @@
#include
#include "base/logging.h"
+#include "base/mutex.h"
#include "profiler/profiler.h"
#include "Common/MsgHandler.h"
-#include "Common/StdMutex.h"
#include "Common/Atomics.h"
#include "Core/CoreTiming.h"
#include "Core/Core.h"
@@ -86,7 +86,7 @@ s64 idledCycles;
s64 lastGlobalTimeTicks;
s64 lastGlobalTimeUs;
-static std::recursive_mutex externalEventSection;
+static recursive_mutex externalEventSection;
// Warning: not included in save state.
void (*advanceCallback)(int cyclesExecuted) = NULL;
@@ -228,7 +228,7 @@ void Shutdown()
delete ev;
}
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
while(eventTsPool)
{
Event *ev = eventTsPool;
@@ -252,7 +252,7 @@ u64 GetIdleTicks()
// schedule things to be executed on the main thread.
void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata)
{
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
Event *ne = GetNewTsEvent();
ne->time = GetTicks() + cyclesIntoFuture;
ne->type = event_type;
@@ -273,7 +273,7 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata)
{
if(false) //Core::IsCPUThread())
{
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
event_types[event_type].callback(userdata, 0);
}
else
@@ -368,7 +368,7 @@ s64 UnscheduleEvent(int event_type, u64 userdata)
s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
{
s64 result = 0;
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
if (!tsFirst)
return result;
while(tsFirst)
@@ -478,7 +478,7 @@ void RemoveEvent(int event_type)
void RemoveThreadsafeEvent(int event_type)
{
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
if (!tsFirst)
{
return;
@@ -552,7 +552,7 @@ void MoveEvents()
{
Common::AtomicStoreRelease(hasTsEvents, 0);
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
// Move events from async queue into main queue
while (tsFirst)
{
@@ -692,7 +692,7 @@ void Event_DoStateOld(PointerWrap &p, BaseEvent *ev)
void DoState(PointerWrap &p)
{
- std::lock_guard lk(externalEventSection);
+ lock_guard lk(externalEventSection);
auto s = p.Section("CoreTiming", 1, 3);
if (!s)
diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp
index 75116abd8f..298ada31a7 100644
--- a/Core/HLE/sceCtrl.cpp
+++ b/Core/HLE/sceCtrl.cpp
@@ -17,6 +17,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include
+#include "base/mutex.h"
#include "Globals.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
@@ -24,7 +25,6 @@
#include "Core/CoreTiming.h"
#include "Core/MemMapHelpers.h"
#include "Common/ChunkFile.h"
-#include "Common/StdMutex.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceDisplay.h"
#include "Core/HLE/sceKernel.h"
@@ -84,7 +84,7 @@ static int ctrlIdleBack = -1;
static int ctrlCycle = 0;
static std::vector waitingThreads;
-static std::recursive_mutex ctrlMutex;
+static recursive_mutex ctrlMutex;
static int ctrlTimer = -1;
@@ -101,7 +101,7 @@ const u32 CTRL_EMU_RAPIDFIRE_MASK = CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT
static void __CtrlUpdateLatch()
{
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
// Copy in the current data to the current buffer.
ctrlBufs[ctrlBuf] = ctrlCurrent;
@@ -144,14 +144,14 @@ static int __CtrlResetLatch()
u32 __CtrlPeekButtons()
{
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
return ctrlCurrent.buttons;
}
void __CtrlPeekAnalog(int stick, float *x, float *y)
{
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
*x = (ctrlCurrent.analog[stick][CTRL_ANALOG_X] - 127.5f) / 127.5f;
*y = -(ctrlCurrent.analog[stick][CTRL_ANALOG_Y] - 127.5f) / 127.5f;
@@ -170,27 +170,27 @@ u32 __CtrlReadLatch()
void __CtrlButtonDown(u32 buttonBit)
{
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
ctrlCurrent.buttons |= buttonBit;
}
void __CtrlButtonUp(u32 buttonBit)
{
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
ctrlCurrent.buttons &= ~buttonBit;
}
void __CtrlSetAnalogX(float x, int stick)
{
u8 scaled = clamp_u8((int)ceilf(x * 127.5f + 127.5f));
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
ctrlCurrent.analog[stick][CTRL_ANALOG_X] = scaled;
}
void __CtrlSetAnalogY(float y, int stick)
{
u8 scaled = clamp_u8((int)ceilf(-y * 127.5f + 127.5f));
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
ctrlCurrent.analog[stick][CTRL_ANALOG_Y] = scaled;
}
@@ -304,7 +304,7 @@ void __CtrlInit()
ctrlIdleBack = -1;
ctrlCycle = 0;
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
ctrlBuf = 1;
ctrlBufRead = 0;
@@ -326,7 +326,7 @@ void __CtrlInit()
void __CtrlDoState(PointerWrap &p)
{
- std::lock_guard guard(ctrlMutex);
+ lock_guard guard(ctrlMutex);
auto s = p.Section("sceCtrl", 1, 3);
if (!s)
diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp
index b9a0321ba0..ee8f3d1aaa 100644
--- a/Core/SaveState.cpp
+++ b/Core/SaveState.cpp
@@ -15,13 +15,14 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+#include
#include
+#include "base/mutex.h"
#include "base/timeutil.h"
#include "base/NativeApp.h"
#include "i18n/i18n.h"
-#include "Common/StdMutex.h"
#include "Common/FileUtil.h"
#include "Common/ChunkFile.h"
@@ -206,7 +207,7 @@ namespace SaveState
static bool needsProcess = false;
static std::vector pending;
- static std::recursive_mutex mutex;
+ static recursive_mutex mutex;
static bool hasLoadedState = false;
// TODO: Should this be configurable?
@@ -250,7 +251,7 @@ namespace SaveState
void Enqueue(SaveState::Operation op)
{
- std::lock_guard guard(mutex);
+ lock_guard guard(mutex);
pending.push_back(op);
// Don't actually run it until next frame.
@@ -486,7 +487,7 @@ namespace SaveState
std::vector Flush()
{
- std::lock_guard guard(mutex);
+ lock_guard guard(mutex);
std::vector copy = pending;
pending.clear();
@@ -670,7 +671,7 @@ namespace SaveState
// Make sure there's a directory for save slots
pspFileSystem.MkDir("ms0:/PSP/PPSSPP_STATE");
- std::lock_guard guard(mutex);
+ lock_guard guard(mutex);
rewindStates.Clear();
hasLoadedState = false;
diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp
index 82a40ef263..416d5767be 100644
--- a/UI/CwCheatScreen.cpp
+++ b/UI/CwCheatScreen.cpp
@@ -15,18 +15,20 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+#include
#include "input/input_state.h"
#include "ui/ui.h"
#include "util/text/utf8.h"
#include "i18n/i18n.h"
+#include "Common/FileUtil.h"
#include "Core/Core.h"
#include "Core/Config.h"
+#include "Core/CwCheat.h"
#include "Core/MIPS/JitCommon/NativeJit.h"
#include "UI/OnScreenDisplay.h"
#include "UI/ui_atlas.h"
-#include "UI/GamepadEmu.h"
#include "UI/MainScreen.h"
#include "UI/EmuScreen.h"
diff --git a/UI/CwCheatScreen.h b/UI/CwCheatScreen.h
index d08e6e160f..22cc35429c 100644
--- a/UI/CwCheatScreen.h
+++ b/UI/CwCheatScreen.h
@@ -15,16 +15,11 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
-#include
-#include "Common/FileUtil.h"
-
#include "base/functional.h"
#include "ui/view.h"
#include "ui/ui_screen.h"
#include "ui/ui_context.h"
-#include "../Core/CwCheat.h"
#include "UI/MiscScreens.h"
-#include "UI/GameSettingsScreen.h"
extern std::string activeCheatFile;
extern std::string gameTitle;
@@ -37,7 +32,6 @@ public:
void processFileOff(std::string deactivatedCheat);
const char * name;
std::string activatedCheat, deactivatedCheat;
- UI::EventReturn OnBack(UI::EventParams ¶ms);
UI::EventReturn OnAddCheat(UI::EventParams ¶ms);
UI::EventReturn OnImportCheat(UI::EventParams ¶ms);
UI::EventReturn OnEditCheatFile(UI::EventParams ¶ms);
diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp
index 244d8bf721..3901033699 100644
--- a/UI/GameInfoCache.cpp
+++ b/UI/GameInfoCache.cpp
@@ -298,6 +298,16 @@ std::string GameInfo::GetTitle() {
return title;
}
+bool GameInfo::IsPending() {
+ lock_guard guard(lock);
+ return pending;
+}
+
+bool GameInfo::IsWorking() {
+ lock_guard guard(lock);
+ return working;
+}
+
void GameInfo::SetTitle(const std::string &newTitle) {
lock_guard guard(lock);
title = newTitle;
@@ -355,6 +365,7 @@ public:
std::string filename = gamePath_;
{
lock_guard lock(info_->lock);
+ info_->working = true;
info_->fileType = Identify_File(info_->GetFileLoader());
}
@@ -581,8 +592,12 @@ handleELF:
info_->saveDataSize = info_->GetSaveDataSizeInBytes();
info_->installDataSize = info_->GetInstallDataSizeInBytes();
}
- info_->pending = false;
+
info_->DisposeFileLoader();
+
+ lock_guard lock(info_->lock);
+ info_->pending = false;
+ info_->working = false;
// ILOG("Completed writing info for %s", info_->GetTitle().c_str());
}
@@ -702,6 +717,18 @@ void GameInfoCache::PurgeType(IdentifiedFileType fileType) {
}
}
+void GameInfoCache::WaitUntilDone(GameInfo *info) {
+ while (info->IsPending()) {
+ if (gameInfoWQ_->WaitUntilDone(false)) {
+ // A true return means everything finished, so bail out.
+ // This way even if something gets stuck, we won't hang.
+ break;
+ }
+
+ // Otherwise, wait again if it's not done...
+ }
+}
+
// Runs on the main thread.
GameInfo *GameInfoCache::GetInfo(Thin3DContext *thin3d, const std::string &gamePath, int wantFlags) {
@@ -735,15 +762,21 @@ again:
if (!info) {
info = new GameInfo();
}
+
{
lock_guard lock(info->lock);
+ if (info->IsWorking()) {
+ // Uh oh, it's currently in process. It could mark pending = false with the wrong wantFlags.
+ // Let's wait it out, then queue.
+ WaitUntilDone(info);
+ }
info->wantFlags |= wantFlags;
+ info->pending = true;
}
GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info);
gameInfoWQ_->Add(item);
- info->pending = true;
info_[gamePath] = info;
return info;
}
diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h
index 1770702162..70eba8749a 100644
--- a/UI/GameInfoCache.h
+++ b/UI/GameInfoCache.h
@@ -22,12 +22,12 @@
#include "base/mutex.h"
#include "file/file_util.h"
-#include "thread/prioritizedworkqueue.h"
#include "Core/ELF/ParamSFO.h"
#include "Core/Loaders.h"
class Thin3DContext;
class Thin3DTexture;
+class PrioritizedWorkQueue;
// A GameInfo holds information about a game, and also lets you do things that the VSH
// does on the PSP, namely checking for and deleting savedata, and similar things.
@@ -98,7 +98,7 @@ public:
: disc_total(0), disc_number(0), region(-1), fileType(FILETYPE_UNKNOWN), paramSFOLoaded(false),
hasConfig(false), iconTexture(nullptr), pic0Texture(nullptr), pic1Texture(nullptr), wantFlags(0),
lastAccessedTime(0.0), timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0),
- gameSize(0), saveDataSize(0), installDataSize(0), pending(true), fileLoader(nullptr) {}
+ gameSize(0), saveDataSize(0), installDataSize(0), pending(true), working(false), fileLoader(nullptr) {}
~GameInfo();
bool Delete(); // Better be sure what you're doing when calling this.
@@ -119,6 +119,9 @@ public:
std::string GetTitle();
void SetTitle(const std::string &newTitle);
+ bool IsPending();
+ bool IsWorking();
+
// Hold this when reading or writing from the GameInfo.
// Don't need to hold it when just passing around the pointer,
// and obviously also not when creating it and holding the only pointer
@@ -164,6 +167,7 @@ public:
u64 saveDataSize;
u64 installDataSize;
bool pending;
+ bool working;
protected:
// Note: this can change while loading, use GetTitle().
@@ -180,7 +184,6 @@ public:
// This creates a background worker thread!
void Clear();
- void ClearTextures();
void PurgeType(IdentifiedFileType fileType);
// All data in GameInfo including iconTexture may be zero the first time you call this
@@ -192,10 +195,7 @@ public:
PrioritizedWorkQueue *WorkQueue() { return gameInfoWQ_; }
- void WaitUntilDone(GameInfo *info) {
- // Hack - should really wait specifically for that item.
- gameInfoWQ_->WaitUntilDone();
- }
+ void WaitUntilDone(GameInfo *info);
private:
void Init();
diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h
index 89224865af..3759057b9e 100644
--- a/UI/GameSettingsScreen.h
+++ b/UI/GameSettingsScreen.h
@@ -100,7 +100,6 @@ private:
UI::EventReturn OnImmersiveModeChange(UI::EventParams &e);
UI::EventReturn OnAdhocGuides(UI::EventParams &e);
- UI::EventReturn OnAudioBackend(UI::EventParams &e);
UI::EventReturn OnSavedataManager(UI::EventParams &e);
UI::EventReturn OnSysInfo(UI::EventParams &e);
@@ -145,7 +144,6 @@ protected:
private:
std::string tempProAdhocServer;
UI::TextView *addrView_;
- UI::EventReturn OnBack(UI::EventParams &e);
UI::EventReturn On0Click(UI::EventParams &e);
UI::EventReturn On1Click(UI::EventParams &e);
UI::EventReturn On2Click(UI::EventParams &e);
diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp
index a30c55036f..7925287eda 100644
--- a/UI/MiscScreens.cpp
+++ b/UI/MiscScreens.cpp
@@ -27,7 +27,9 @@
#include "ui/view.h"
#include "ui/viewgroup.h"
#include "ui/ui.h"
+#include "util/random/rng.h"
#include "file/vfs.h"
+#include "UI/ui_atlas.h"
#include "UI/MiscScreens.h"
#include "UI/EmuScreen.h"
#include "UI/MainScreen.h"
@@ -35,12 +37,11 @@
#include "Core/Config.h"
#include "Core/Host.h"
#include "Core/System.h"
-#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/MIPS/JitCommon/NativeJit.h"
#include "Core/HLE/sceUtility.h"
-#include "Common/CPUDetect.h"
#include "Common/FileUtil.h"
#include "GPU/GPUState.h"
+#include "GPU/Common/PostShader.h"
#include "ui_atlas.h"
@@ -48,13 +49,6 @@
#pragma execution_character_set("utf-8")
#endif
-#include "base/timeutil.h"
-#include "base/colorutil.h"
-#include "gfx_es2/draw_buffer.h"
-#include "util/random/rng.h"
-
-#include "UI/ui_atlas.h"
-
static const int symbols[4] = {
I_CROSS,
I_CIRCLE,
diff --git a/UI/MiscScreens.h b/UI/MiscScreens.h
index e25f476b44..1885110b13 100644
--- a/UI/MiscScreens.h
+++ b/UI/MiscScreens.h
@@ -24,7 +24,8 @@
#include "file/file_util.h"
#include "base/functional.h"
#include "ui/ui_screen.h"
-#include "GPU/Common/PostShader.h"
+
+struct ShaderInfo;
extern std::string boot_filename;
diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp
index 58bae28060..eb4646e5a2 100644
--- a/UI/OnScreenDisplay.cpp
+++ b/UI/OnScreenDisplay.cpp
@@ -55,7 +55,7 @@ restart:
void OnScreenMessages::Show(const std::string &text, float duration_s, uint32_t color, int icon, bool checkUnique, const char *id) {
double now = time_now_d();
- std::lock_guard guard(mutex_);
+ lock_guard guard(mutex_);
if (checkUnique) {
for (auto iter = messages_.begin(); iter != messages_.end(); ++iter) {
if (iter->text == text || (id && iter->id && !strcmp(iter->id, id))) {
diff --git a/UI/OnScreenDisplay.h b/UI/OnScreenDisplay.h
index 208f27d27a..8a0c6c17e0 100644
--- a/UI/OnScreenDisplay.h
+++ b/UI/OnScreenDisplay.h
@@ -3,9 +3,9 @@
#include
#include
+#include "base/mutex.h"
#include "base/basictypes.h"
#include "math/geom2d.h"
-#include "Common/StdMutex.h"
#include "ui/view.h"
@@ -39,7 +39,7 @@ public:
private:
std::list messages_;
- std::recursive_mutex mutex_;
+ recursive_mutex mutex_;
};
class OnScreenMessagesView : public UI::InertView {
diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp
index abce83ca07..609c5b3aef 100644
--- a/UI/PauseScreen.cpp
+++ b/UI/PauseScreen.cpp
@@ -16,8 +16,10 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "i18n/i18n.h"
+#include "gfx_es2/draw_buffer.h"
#include "ui/view.h"
#include "ui/viewgroup.h"
+#include "ui/ui_context.h"
#include "ui/ui_screen.h"
#include "thin3d/thin3d.h"
@@ -40,9 +42,6 @@
#include "UI/MainScreen.h"
#include "UI/GameInfoCache.h"
-#include "gfx_es2/draw_buffer.h"
-#include "ui/ui_context.h"
-
void AsyncImageFileView::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
if (texture_) {
float texw = (float)texture_->Width();
diff --git a/UI/Store.cpp b/UI/Store.cpp
index 74bc3fef56..b9569698cb 100644
--- a/UI/Store.cpp
+++ b/UI/Store.cpp
@@ -29,6 +29,7 @@
#include "Common/StringUtils.h"
#include "Core/Config.h"
#include "Core/System.h"
+#include "Core/Util/GameManager.h"
#include "UI/EmuScreen.h"
#include "UI/Store.h"
diff --git a/UI/Store.h b/UI/Store.h
index fc1c35edfb..9f00dc7524 100644
--- a/UI/Store.h
+++ b/UI/Store.h
@@ -22,7 +22,6 @@
#include "ui/viewgroup.h"
#include "net/http_client.h"
-#include "Core/Util/GameManager.h"
#include "UI/MiscScreens.h"
// Game screen: Allows you to start a game, delete saves, delete the game,
@@ -68,7 +67,6 @@ public:
protected:
virtual void CreateViews();
UI::EventReturn OnGameSelected(UI::EventParams &e);
- UI::EventReturn OnCategorySelected(UI::EventParams &e);
UI::EventReturn OnRetry(UI::EventParams &e);
UI::EventReturn OnGameLaunch(UI::EventParams &e);
diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp
index aaa541281f..59e698ffb5 100644
--- a/android/jni/app-android.cpp
+++ b/android/jni/app-android.cpp
@@ -19,6 +19,7 @@
#include "base/NativeApp.h"
#include "base/logging.h"
#include "base/timeutil.h"
+#include "thread/prioritizedworkqueue.h"
#include "thread/threadutil.h"
#include "file/zip_read.h"
#include "input/input_state.h"
diff --git a/ext/native/base/mutex.h b/ext/native/base/mutex.h
index f1f9a3cd44..765bd84824 100644
--- a/ext/native/base/mutex.h
+++ b/ext/native/base/mutex.h
@@ -19,6 +19,8 @@
#undef p
#undef DrawText
#undef itoa
+#undef min
+#undef max
#else
#include
diff --git a/ext/native/thread/prioritizedworkqueue.cpp b/ext/native/thread/prioritizedworkqueue.cpp
index 421d08b92d..8d6d7561cd 100644
--- a/ext/native/thread/prioritizedworkqueue.cpp
+++ b/ext/native/thread/prioritizedworkqueue.cpp
@@ -33,28 +33,45 @@ void PrioritizedWorkQueue::Flush() {
ILOG("Flushed %d un-executed tasks", flush_count);
}
-void PrioritizedWorkQueue::WaitUntilDone() {
- if (queue_.empty())
- return;
- // This could be made more elegant..
- while (true) {
- bool empty;
- {
- lock_guard guard(mutex_);
- empty = queue_.empty() && !working_;
- }
- if (empty) {
- break;
- }
- sleep_ms(10);
+bool PrioritizedWorkQueue::WaitUntilDone(bool all) {
+ // We'll lock drain this entire time, so make sure you follow that lock ordering.
+ lock_guard guard(drainMutex_);
+ if (AllItemsDone()) {
+ return true;
}
+
+ while (!AllItemsDone()) {
+ drain_.wait(drainMutex_);
+ if (!all) {
+ // Return whether empty or not, something just drained.
+ return AllItemsDone();
+ }
+ }
+
+ return true;
}
+void PrioritizedWorkQueue::NotifyDrain() {
+ lock_guard guard(drainMutex_);
+ drain_.notify_one();
+}
+
+bool PrioritizedWorkQueue::AllItemsDone() {
+ lock_guard guard(mutex_);
+ return queue_.empty() && !working_;
+}
// The worker should simply call this in a loop. Will block when appropriate.
PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() {
+ {
+ lock_guard guard(mutex_);
+ working_ = false; // The thread only calls Pop if it's done.
+ }
+
+ // Important: make sure mutex_ is not locked while draining.
+ NotifyDrain();
+
lock_guard guard(mutex_);
- working_ = false; // The thread only calls Pop if it's done.
if (done_) {
return 0;
}
diff --git a/ext/native/thread/prioritizedworkqueue.h b/ext/native/thread/prioritizedworkqueue.h
index 9ebfd21df0..5d3acea216 100644
--- a/ext/native/thread/prioritizedworkqueue.h
+++ b/ext/native/thread/prioritizedworkqueue.h
@@ -34,17 +34,22 @@ public:
void Flush();
bool Done() { return done_; }
void Stop();
- void WaitUntilDone();
+ bool WaitUntilDone(bool all = true);
bool IsWorking() {
return working_;
}
private:
+ void NotifyDrain();
+ bool AllItemsDone();
+
bool done_;
bool working_;
recursive_mutex mutex_;
+ recursive_mutex drainMutex_;
condition_variable notEmpty_;
+ condition_variable drain_;
std::vector queue_;