- The AsyncExeuctor does now clean itself in 50ms intervals (still could produce dead locks which sucks)

- Only allow a maximum of 10 "tasks" at the same time.
- Increase the stack size of the "Application" which hopefully improves stability?
This commit is contained in:
Maschell 2020-02-20 02:05:54 +01:00
parent d97d5ed325
commit 358f368462
5 changed files with 90 additions and 17 deletions

View File

@ -41,7 +41,7 @@ bool Application::exitApplication = false;
bool Application::quitRequest = false;
Application::Application()
: CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x20000)
: CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x800000)
, bgMusic(NULL)
, video(NULL)
, mainWindow(NULL)
@ -59,6 +59,8 @@ Application::Application()
bgMusic->Play();
bgMusic->SetVolume(50);
AsyncExecutor::execute([] {DEBUG_FUNCTION_LINE("Hello\n");});
exitApplication = false;
uint64_t titleID = OSGetTitleID();

View File

@ -13,12 +13,12 @@
#include "fs/FSUtils.h"
#include "utils/logger.h"
#include "utils/StringTools.h"
#include "system/CMutex.h"
void GameList::clear() {
for (auto const& x : fullGameList) {
if(x != NULL) {
if(x->imageData != NULL) {
DEBUG_FUNCTION_LINE("Delete the image data\n");
delete x->imageData;
x->imageData = NULL;
}
@ -80,8 +80,10 @@ int32_t GameList::readGameList() {
titles.resize(realTitleCount);
}
CMutex extraInfoMutex;
for (auto title_candidate : titles) {
if(true || (title_candidate.titleId & 0xFFFFFFFF00000000L) == 0x0005000000000000L) {
if((title_candidate.titleId & 0xFFFFFFFF00000000L) == 0x0005000000000000L) {
gameInfo* newGameInfo = new gameInfo;
newGameInfo->titleId = title_candidate.titleId;
newGameInfo->gamePath = title_candidate.path;
@ -91,6 +93,39 @@ int32_t GameList::readGameList() {
fullGameList.push_back(newGameInfo);
titleAdded(newGameInfo);
cnt++;
AsyncExecutor::execute([newGameInfo, this, &extraInfoMutex] {
extraInfoMutex.lock();
DEBUG_FUNCTION_LINE("Load extra infos of %016llX\n",newGameInfo->titleId);
ACPMetaXml* meta = (ACPMetaXml*)calloc(1, 0x4000); //TODO fix wut
if(meta) {
auto acp = ACPGetTitleMetaXml(newGameInfo->titleId, meta);
if(acp >= 0) {
newGameInfo->name = meta->shortname_en;
}
free(meta);
}
if(newGameInfo->imageData == NULL) {
std::string filepath = "fs:" + newGameInfo->gamePath + META_PATH + "/iconTex.tga";
uint8_t *buffer = NULL;
uint32_t bufferSize = 0;
int iResult = FSUtils::LoadFileToMem(filepath.c_str(), &buffer, &bufferSize);
if(iResult > 0) {
GuiImageData * imageData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MODE_MIRROR);
if(imageData) {
newGameInfo->imageData = imageData;
}
//! free original image buffer which is converted to texture now and not needed anymore
free(buffer);
}
}
DCFlushRange(newGameInfo, sizeof(gameInfo));
titleUpdated(newGameInfo);
extraInfoMutex.unlock();
});
}
}

View File

@ -124,10 +124,7 @@ void MainWindow::OnGameTitleUpdated(gameInfo * info) {
}
void MainWindow::OnGameTitleAdded(gameInfo * info) {
DEBUG_FUNCTION_LINE("%08X\n", info);
if(info == NULL) {
return;
}
currentTvFrame->OnGameTitleAdded(info);
if(currentTvFrame != currentDrcFrame) {
currentDrcFrame->OnGameTitleAdded(info);

View File

@ -6,15 +6,39 @@ AsyncExecutor * AsyncExecutor::instance = NULL;
void AsyncExecutor::pushForDelete(GuiElement * ptr) {
execute([ptr] {delete ptr;});
}
AsyncExecutor::AsyncExecutor() {
thread = new std::thread([&]() {
while(!exitThread) {
instance->mutex.lock();
auto it = instance->elements.begin();
while (it != instance->elements.end()) {
auto future = it;
auto status = future->wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
it = instance->elements.erase(it);
} else {
++it;
}
}
instance->mutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
DCFlushRange((void*)&exitThread, sizeof(exitThread));
}
});
thread->detach();
}
void AsyncExecutor::execute(std::function<void()> func) {
if(!instance) {
instance = new AsyncExecutor();
}
instance->elements.push(std::async(std::launch::async,func));
if(instance->elements.size() >= 25){
//DEBUG_FUNCTION_LINE("Wait on queue %d\n",instance->elements.size());
instance->elements.front().get();
instance->elements.pop();
while(instance->elements.size() > 10) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
instance->mutex.lock();
instance->elements.push_back(std::async(std::launch::async,func));
instance->mutex.unlock();
}

View File

@ -1,8 +1,14 @@
#pragma once
#ifndef ___ASYNCEXECUTER_H_
#define ___ASYNCEXECUTER_H_
#include <queue>
#include <vector>
#include <future>
#include <thread>
#include <gui/GuiElement.h>
#include <system/CMutex.h>
#include <coreinit/cache.h>
#include "utils/logger.h"
class AsyncExecutor {
public:
@ -19,8 +25,17 @@ public:
private:
static AsyncExecutor *instance;
AsyncExecutor() {}
~AsyncExecutor() {}
AsyncExecutor();
std::queue<std::future<void>> elements;
~AsyncExecutor() {
exitThread = true;
DCFlushRange((void*)&exitThread, sizeof(exitThread));
}
CMutex mutex;
std::thread * thread;
volatile bool exitThread = false;
std::vector<std::future<void>> elements;
};
#endif