1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-05-17 07:11:28 +00:00

Wait for the reloading cells thread on DataFilesPage destruction

Run a single thread and notify it when it has to reload cells.
This commit is contained in:
elsid 2025-05-04 13:25:33 +02:00
parent 0d27dc2336
commit 4a18c23e2d
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
3 changed files with 58 additions and 21 deletions

View file

@ -231,6 +231,7 @@
Bug #8378: Korean bitmap fonts are unusable Bug #8378: Korean bitmap fonts are unusable
Bug #8439: Creatures without models can crash the game Bug #8439: Creatures without models can crash the game
Bug #8441: Freeze when using video main menu replacers Bug #8441: Freeze when using video main menu replacers
Bug #8445: Launcher crashes on exit when cell name loading thread is still running
Bug #8462: Crashes when resizing the window on macOS Bug #8462: Crashes when resizing the window on macOS
Feature #1415: Infinite fall failsafe Feature #1415: Infinite fall failsafe
Feature #2566: Handle NAM9 records for manual cell references Feature #2566: Handle NAM9 records for manual cell references

View file

@ -159,6 +159,7 @@ Launcher::DataFilesPage::DataFilesPage(const Files::ConfigurationManager& cfg, C
, mGameSettings(gameSettings) , mGameSettings(gameSettings)
, mLauncherSettings(launcherSettings) , mLauncherSettings(launcherSettings)
, mNavMeshToolInvoker(new Process::ProcessInvoker(this)) , mNavMeshToolInvoker(new Process::ProcessInvoker(this))
, mReloadCellsThread(&DataFilesPage::reloadCells, this)
{ {
ui.setupUi(this); ui.setupUi(this);
setObjectName("DataFilesPage"); setObjectName("DataFilesPage");
@ -205,6 +206,16 @@ Launcher::DataFilesPage::DataFilesPage(const Files::ConfigurationManager& cfg, C
slotAddonDataChanged(); slotAddonDataChanged();
} }
Launcher::DataFilesPage::~DataFilesPage()
{
{
const std::lock_guard lock(mReloadCellsMutex);
mAbortReloadCells = true;
mStartReloadCells.notify_one();
}
mReloadCellsThread.join();
}
void Launcher::DataFilesPage::buildView() void Launcher::DataFilesPage::buildView()
{ {
QToolButton* refreshButton = mSelector->refreshButton(); QToolButton* refreshButton = mSelector->refreshButton();
@ -991,31 +1002,45 @@ bool Launcher::DataFilesPage::showDeleteMessageBox(const QString& text)
void Launcher::DataFilesPage::slotAddonDataChanged() void Launcher::DataFilesPage::slotAddonDataChanged()
{ {
QStringList selectedFiles = selectedFilePaths(); QStringList selectedFiles = selectedFilePaths();
if (previousSelectedFiles != selectedFiles) if (mSelectedFiles != selectedFiles)
{ {
previousSelectedFiles = selectedFiles; const std::lock_guard lock(mReloadCellsMutex);
// Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a mSelectedFiles = std::move(selectedFiles);
// barely perceptible UI lag. Splitting into its own thread to alleviate that. mReloadCells = true;
std::thread loadCellsThread(&DataFilesPage::reloadCells, this, selectedFiles); mStartReloadCells.notify_one();
loadCellsThread.detach();
} }
} }
// Mutex lock to run reloadCells synchronously. void Launcher::DataFilesPage::reloadCells()
static std::mutex reloadCellsMutex;
void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles)
{ {
// Use a mutex lock so that we can prevent two threads from executing the rest of this code at the same time std::unique_lock lock(mReloadCellsMutex);
// Based on https://stackoverflow.com/a/5429695/531762
std::unique_lock<std::mutex> lock(reloadCellsMutex);
// The following code will run only if there is not another thread currently running it while (true)
CellNameLoader cellNameLoader; {
QSet<QString> set = cellNameLoader.getCellNames(selectedFiles); mStartReloadCells.wait(lock);
QStringList cellNamesList(set.begin(), set.end());
std::sort(cellNamesList.begin(), cellNamesList.end()); if (mAbortReloadCells)
emit signalLoadedCellsChanged(cellNamesList); return;
if (!std::exchange(mReloadCells, false))
continue;
QStringList selectedFiles = mSelectedFiles;
lock.unlock();
CellNameLoader cellNameLoader;
QSet<QString> set = cellNameLoader.getCellNames(selectedFiles);
QStringList cellNamesList(set.begin(), set.end());
std::sort(cellNamesList.begin(), cellNamesList.end());
emit signalLoadedCellsChanged(std::move(cellNamesList));
lock.lock();
if (mAbortReloadCells)
return;
}
} }
void Launcher::DataFilesPage::startNavMeshTool() void Launcher::DataFilesPage::startNavMeshTool()

View file

@ -10,6 +10,10 @@
#include <QStringList> #include <QStringList>
#include <QWidget> #include <QWidget>
#include <condition_variable>
#include <mutex>
#include <thread>
class QSortFilterProxyModel; class QSortFilterProxyModel;
class QAbstractItemModel; class QAbstractItemModel;
class QMenu; class QMenu;
@ -47,6 +51,7 @@ namespace Launcher
public: public:
explicit DataFilesPage(const Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings, explicit DataFilesPage(const Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings,
Config::LauncherSettings& launcherSettings, MainDialog* parent = nullptr); Config::LauncherSettings& launcherSettings, MainDialog* parent = nullptr);
~DataFilesPage();
QAbstractItemModel* profilesModel() const; QAbstractItemModel* profilesModel() const;
@ -119,7 +124,7 @@ namespace Launcher
Config::LauncherSettings& mLauncherSettings; Config::LauncherSettings& mLauncherSettings;
QString mPreviousProfile; QString mPreviousProfile;
QStringList previousSelectedFiles; QStringList mSelectedFiles;
QString mDataLocal; QString mDataLocal;
QStringList mKnownArchives; QStringList mKnownArchives;
QStringList mNewDataDirs; QStringList mNewDataDirs;
@ -127,6 +132,12 @@ namespace Launcher
Process::ProcessInvoker* mNavMeshToolInvoker; Process::ProcessInvoker* mNavMeshToolInvoker;
NavMeshToolProgress mNavMeshToolProgress; NavMeshToolProgress mNavMeshToolProgress;
bool mReloadCells = false;
bool mAbortReloadCells = false;
std::mutex mReloadCellsMutex;
std::condition_variable mStartReloadCells;
std::thread mReloadCellsThread;
void addArchive(const QString& name, Qt::CheckState selected, int row = -1); void addArchive(const QString& name, Qt::CheckState selected, int row = -1);
void addArchivesFromDir(const QString& dir); void addArchivesFromDir(const QString& dir);
void buildView(); void buildView();
@ -140,7 +151,7 @@ namespace Launcher
void addProfile(const QString& profile, bool setAsCurrent); void addProfile(const QString& profile, bool setAsCurrent);
void checkForDefaultProfile(); void checkForDefaultProfile();
void populateFileViews(const QString& contentModelName); void populateFileViews(const QString& contentModelName);
void reloadCells(QStringList selectedFiles); void reloadCells();
void refreshDataFilesView(); void refreshDataFilesView();
void updateNavMeshProgress(int minDataSize); void updateNavMeshProgress(int minDataSize);
void slotCopySelectedItemsPaths(); void slotCopySelectedItemsPaths();