mirror of
https://github.com/OpenMW/openmw.git
synced 2025-05-17 22: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:
parent
0d27dc2336
commit
4a18c23e2d
3 changed files with 58 additions and 21 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
while (true)
|
||||||
|
{
|
||||||
|
mStartReloadCells.wait(lock);
|
||||||
|
|
||||||
|
if (mAbortReloadCells)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!std::exchange(mReloadCells, false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QStringList selectedFiles = mSelectedFiles;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
// The following code will run only if there is not another thread currently running it
|
|
||||||
CellNameLoader cellNameLoader;
|
CellNameLoader cellNameLoader;
|
||||||
QSet<QString> set = cellNameLoader.getCellNames(selectedFiles);
|
QSet<QString> set = cellNameLoader.getCellNames(selectedFiles);
|
||||||
QStringList cellNamesList(set.begin(), set.end());
|
QStringList cellNamesList(set.begin(), set.end());
|
||||||
std::sort(cellNamesList.begin(), cellNamesList.end());
|
std::sort(cellNamesList.begin(), cellNamesList.end());
|
||||||
emit signalLoadedCellsChanged(cellNamesList);
|
|
||||||
|
emit signalLoadedCellsChanged(std::move(cellNamesList));
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
if (mAbortReloadCells)
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::startNavMeshTool()
|
void Launcher::DataFilesPage::startNavMeshTool()
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue