Skip to content
Permalink
Browse files

Merge pull request #12371 from unknownbrackets/thread-detach

Avoid thread.detach(), join when needed instead
  • Loading branch information...
hrydgard committed Oct 7, 2019
2 parents 8e44230 + c9c34c4 commit 13f87301cfefa6e592436d4dbde2dca1df353a73
@@ -109,9 +109,11 @@ void CachingFileLoader::ShutdownCache() {
// TODO: Maybe add some hint that deletion is coming soon?
// We can't delete while the thread is running, so have to wait.
// This should only happen from the menu.
while (aheadThread_) {
while (aheadThreadRunning_) {
sleep_ms(1);
}
if (aheadThread_.joinable())
aheadThread_.join();

std::lock_guard<std::recursive_mutex> guard(blocksMutex_);
for (auto block : blocks_) {
@@ -252,7 +254,7 @@ bool CachingFileLoader::MakeCacheSpaceFor(size_t blocks, bool readingAhead) {

void CachingFileLoader::StartReadAhead(s64 pos) {
std::lock_guard<std::recursive_mutex> guard(blocksMutex_);
if (aheadThread_) {
if (aheadThreadRunning_) {
// Already going.
return;
}
@@ -261,8 +263,10 @@ void CachingFileLoader::StartReadAhead(s64 pos) {
return;
}

aheadThread_ = true;
std::thread th([this, pos] {
aheadThreadRunning_ = true;
if (aheadThread_.joinable())
aheadThread_.join();
aheadThread_ = std::thread([this, pos] {
setCurrentThreadName("FileLoaderReadAhead");

std::unique_lock<std::recursive_mutex> guard(blocksMutex_);
@@ -278,7 +282,6 @@ void CachingFileLoader::StartReadAhead(s64 pos) {
}
}

aheadThread_ = false;
aheadThreadRunning_ = false;
});
th.detach();
}
@@ -19,6 +19,7 @@

#include <map>
#include <mutex>
#include <thread>

#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
@@ -75,6 +76,7 @@ class CachingFileLoader : public ProxiedFileLoader {

std::map<s64, BlockInfo> blocks_;
std::recursive_mutex blocksMutex_;
bool aheadThread_ = false;
bool aheadThreadRunning_ = false;
std::thread aheadThread_;
std::once_flag preparedFlag_;
};
@@ -105,9 +105,11 @@ void RamCachingFileLoader::ShutdownCache() {

// We can't delete while the thread is running, so have to wait.
// This should only happen from the menu.
while (aheadThread_) {
while (aheadThreadRunning_) {
sleep_ms(1);
}
if (aheadThread_.joinable())
aheadThread_.join();

std::lock_guard<std::mutex> guard(blocksMutex_);
blocks_.clear();
@@ -118,7 +120,7 @@ void RamCachingFileLoader::ShutdownCache() {
}

void RamCachingFileLoader::Cancel() {
if (aheadThread_) {
if (aheadThreadRunning_) {
std::lock_guard<std::mutex> guard(blocksMutex_);
aheadCancel_ = true;
}
@@ -213,14 +215,16 @@ void RamCachingFileLoader::StartReadAhead(s64 pos) {

std::lock_guard<std::mutex> guard(blocksMutex_);
aheadPos_ = pos;
if (aheadThread_) {
if (aheadThreadRunning_) {
// Already going.
return;
}

aheadThread_ = true;
aheadThreadRunning_ = true;
aheadCancel_ = false;
std::thread th([this] {
if (aheadThread_.joinable())
aheadThread_.join();
aheadThread_ = std::thread([this] {
setCurrentThreadName("FileLoaderReadAhead");

while (aheadRemaining_ != 0 && !aheadCancel_) {
@@ -243,9 +247,8 @@ void RamCachingFileLoader::StartReadAhead(s64 pos) {
}
}

aheadThread_ = false;
aheadThreadRunning_ = false;
});
th.detach();
}

u32 RamCachingFileLoader::NextAheadBlock() {
@@ -19,6 +19,7 @@

#include <vector>
#include <mutex>
#include <thread>

#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
@@ -65,6 +66,7 @@ class RamCachingFileLoader : public ProxiedFileLoader {
std::mutex blocksMutex_;
u32 aheadRemaining_;
s64 aheadPos_;
bool aheadThread_ = false;
std::thread aheadThread_;
bool aheadThreadRunning_ = false;
bool aheadCancel_ = false;
};
@@ -601,7 +601,6 @@ void __IoInit() {
if (ioManagerThreadEnabled) {
Core_ListenLifecycle(&__IoWakeManager);
ioManagerThread = new std::thread(&__IoManagerThread);
ioManagerThread->detach();
}

__KernelRegisterWaitTypeFuncs(WAITTYPE_ASYNCIO, __IoAsyncBeginCallback, __IoAsyncEndCallback);
@@ -651,9 +650,10 @@ void __IoShutdown() {
ioManagerThreadEnabled = false;
ioManager.SyncThread();
ioManager.FinishEventLoop();
if (ioManagerThread != NULL) {
if (ioManagerThread != nullptr) {
ioManagerThread->join();
delete ioManagerThread;
ioManagerThread = NULL;
ioManagerThread = nullptr;
ioManager.Shutdown();
}

@@ -57,6 +57,8 @@
#include "Core/HLE/sceKernelModule.h"
#include "Core/HLE/sceKernelMemory.h"

static std::thread loadingThread;

static void UseLargeMem(int memsize) {
if (memsize != 1) {
// Nothing requested.
@@ -256,7 +258,11 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
host->SendUIMessage("config_loaded", "");
INFO_LOG(LOADER,"Loading %s...", bootpath.c_str());

std::thread th([bootpath] {
PSPLoaders_Shutdown();
// Note: this thread reads the game binary, loads caches, and links HLE while UI spins.
// To do something deterministically when the game starts, disabling this thread won't be enough.
// Instead: Use Core_ListenLifecycle() or watch coreState.
loadingThread = std::thread([bootpath] {
setCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
@@ -273,7 +279,6 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
PSP_CoreParameter().fileToStart = "";
}
});
th.detach();
return true;
}

@@ -379,7 +384,9 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
}
// End of temporary code

std::thread th([finalName] {
PSPLoaders_Shutdown();
// Note: See Load_PSP_ISO for notes about this thread.
loadingThread = std::thread([finalName] {
setCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
@@ -394,15 +401,16 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
PSP_CoreParameter().fileToStart = "";
}
});
th.detach();
return true;
}

bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
BlobFileSystem *umd = new BlobFileSystem(&pspFileSystem, fileLoader, "data.ppdmp");
pspFileSystem.Mount("disc0:", umd);

std::thread th([] {
PSPLoaders_Shutdown();
// Note: See Load_PSP_ISO for notes about this thread.
loadingThread = std::thread([] {
setCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
@@ -417,6 +425,10 @@ bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
PSP_CoreParameter().fileToStart = "";
}
});
th.detach();
return true;
}

void PSPLoaders_Shutdown() {
if (loadingThread.joinable())
loadingThread.join();
}
@@ -26,3 +26,4 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string);
bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string);
void InitMemoryForGameISO(FileLoader *fileLoader);
void InitMemoryForGamePBP(FileLoader *fileLoader);
void PSPLoaders_Shutdown();
@@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.

#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
@@ -70,6 +71,13 @@ namespace Reporting
// The latest compatibility result from the server.
static std::vector<std::string> lastCompatResult;

static std::mutex pendingMessageLock;
static std::condition_variable pendingMessageCond;
static std::deque<int> pendingMessages;
static bool pendingMessagesDone = false;
static std::thread messageThread;
static std::thread compatThread;

enum class RequestType
{
NONE,
@@ -93,6 +101,7 @@ namespace Reporting
static std::condition_variable crcCond;
static std::string crcFilename;
static std::map<std::string, u32> crcResults;
static std::thread crcThread;

static int CalculateCRCThread() {
setCurrentThreadName("ReportCRC");
@@ -133,8 +142,7 @@ namespace Reporting
}

crcFilename = gamePath;
std::thread th(CalculateCRCThread);
th.detach();
crcThread = std::thread(CalculateCRCThread);
}

u32 RetrieveCRC() {
@@ -148,6 +156,8 @@ namespace Reporting
it = crcResults.find(gamePath);
}

if (crcThread.joinable())
crcThread.join();
return it->second;
}

@@ -297,10 +307,20 @@ namespace Reporting
logOnceUsed.clear();
everUnsupported = false;
currentSupported = IsSupported();
pendingMessagesDone = false;
}

void Shutdown()
{
pendingMessageLock.lock();
pendingMessagesDone = true;
pendingMessageCond.notify_one();
pendingMessageLock.unlock();
if (compatThread.joinable())
compatThread.join();
if (messageThread.joinable())
messageThread.join();

// Just so it can be enabled in the menu again.
Init();
}
@@ -543,6 +563,28 @@ namespace Reporting
return -1;
}

int ProcessPending() {
setCurrentThreadName("Report");

std::unique_lock<std::mutex> guard(pendingMessageLock);
while (!pendingMessagesDone) {
while (!pendingMessages.empty() && !pendingMessagesDone) {
int pos = pendingMessages.front();
pendingMessages.pop_front();

guard.unlock();
Process(pos);
guard.lock();
}
if (pendingMessagesDone) {
break;
}
pendingMessageCond.wait(guard);
}

return 0;
}

void ReportMessage(const char *message, ...)
{
if (!IsEnabled() || CheckSpamLimited())
@@ -565,8 +607,13 @@ namespace Reporting
payload.string1 = message;
payload.string2 = temp;

std::thread th(Process, pos);
th.detach();
std::lock_guard<std::mutex> guard(pendingMessageLock);
pendingMessages.push_back(pos);
pendingMessageCond.notify_one();

if (!messageThread.joinable()) {
messageThread = std::thread(ProcessPending);
}
}

void ReportMessageFormatted(const char *message, const char *formatted)
@@ -582,8 +629,13 @@ namespace Reporting
payload.string1 = message;
payload.string2 = formatted;

std::thread th(Process, pos);
th.detach();
std::lock_guard<std::mutex> guard(pendingMessageLock);
pendingMessages.push_back(pos);
pendingMessageCond.notify_one();

if (!messageThread.joinable()) {
messageThread = std::thread(ProcessPending);
}
}

void ReportCompatibility(const char *compat, int graphics, int speed, int gameplay, const std::string &screenshotFilename)
@@ -602,8 +654,9 @@ namespace Reporting
payload.int2 = speed;
payload.int3 = gameplay;

std::thread th(Process, pos);
th.detach();
if (compatThread.joinable())
compatThread.join();
compatThread = std::thread(Process, pos);
}

std::vector<std::string> CompatibilitySuggestions() {

0 comments on commit 13f8730

Please sign in to comment.
You can’t perform that action at this time.