Merge pull request #628 from flowln/fix_multiple_resource_packs_crash
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/624
This commit is contained in:
		@@ -20,6 +20,7 @@ ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent) : QAbstractL
 | 
			
		||||
    m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
 | 
			
		||||
 | 
			
		||||
    connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &ResourceFolderModel::directoryChanged);
 | 
			
		||||
    connect(&m_helper_thread_task, &ConcurrentTask::finished, this, [this]{ m_helper_thread_task.clear(); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResourceFolderModel::~ResourceFolderModel()
 | 
			
		||||
@@ -275,7 +276,11 @@ void ResourceFolderModel::resolveResource(Resource* res)
 | 
			
		||||
    connect(
 | 
			
		||||
        task, &Task::finished, this, [=] { m_active_parse_tasks.remove(ticket); }, Qt::ConnectionType::QueuedConnection);
 | 
			
		||||
 | 
			
		||||
    QThreadPool::globalInstance()->start(task);
 | 
			
		||||
    m_helper_thread_task.addTask(task);
 | 
			
		||||
 | 
			
		||||
    if (!m_helper_thread_task.isRunning()) {
 | 
			
		||||
        QThreadPool::globalInstance()->start(&m_helper_thread_task);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceFolderModel::onUpdateSucceeded()
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#include "Resource.h"
 | 
			
		||||
 | 
			
		||||
#include "tasks/Task.h"
 | 
			
		||||
#include "tasks/ConcurrentTask.h"
 | 
			
		||||
 | 
			
		||||
class QSortFilterProxyModel;
 | 
			
		||||
 | 
			
		||||
@@ -197,6 +198,7 @@ class ResourceFolderModel : public QAbstractListModel {
 | 
			
		||||
    // Represents the relationship between a resource's internal ID and it's row position on the model.
 | 
			
		||||
    QMap<QString, int> m_resources_index;
 | 
			
		||||
 | 
			
		||||
    ConcurrentTask m_helper_thread_task;
 | 
			
		||||
    QMap<int, Task::Ptr> m_active_parse_tasks;
 | 
			
		||||
    std::atomic<int> m_next_resolution_ticket = 0;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ auto NetJob::getFailedFiles() -> QList<QString>
 | 
			
		||||
 | 
			
		||||
void NetJob::updateState()
 | 
			
		||||
{
 | 
			
		||||
    emit progress(m_done.count(), m_total_size);
 | 
			
		||||
    emit progress(m_done.count(), totalSize());
 | 
			
		||||
    setStatus(tr("Executing %1 task(s) (%2 out of %3 are done)")
 | 
			
		||||
                  .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(m_total_size)));
 | 
			
		||||
                  .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(totalSize())));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,18 +27,13 @@ auto ConcurrentTask::getStepTotalProgress() const -> qint64
 | 
			
		||||
 | 
			
		||||
void ConcurrentTask::addTask(Task::Ptr task)
 | 
			
		||||
{
 | 
			
		||||
    if (!isRunning())
 | 
			
		||||
        m_queue.append(task);
 | 
			
		||||
    else
 | 
			
		||||
        qWarning() << "Tried to add a task to a running concurrent task!";
 | 
			
		||||
    m_queue.append(task);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConcurrentTask::executeTask()
 | 
			
		||||
{
 | 
			
		||||
    m_total_size = m_queue.size();
 | 
			
		||||
 | 
			
		||||
    // Start the least amount of tasks needed, but at least one
 | 
			
		||||
    int num_starts = std::max(1, std::min(m_total_max_size, m_total_size));
 | 
			
		||||
    int num_starts = qMax(1, qMin(m_total_max_size, m_queue.size()));
 | 
			
		||||
    for (int i = 0; i < num_starts; i++) {
 | 
			
		||||
        QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection);
 | 
			
		||||
    }
 | 
			
		||||
@@ -73,6 +68,20 @@ bool ConcurrentTask::abort()
 | 
			
		||||
    return suceedeed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConcurrentTask::clear()
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(!isRunning());
 | 
			
		||||
 | 
			
		||||
    m_done.clear();
 | 
			
		||||
    m_failed.clear();
 | 
			
		||||
    m_queue.clear();
 | 
			
		||||
 | 
			
		||||
    m_aborted = false;
 | 
			
		||||
 | 
			
		||||
    m_progress = 0;
 | 
			
		||||
    m_stepProgress = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConcurrentTask::startNext()
 | 
			
		||||
{
 | 
			
		||||
    if (m_aborted || m_doing.count() > m_total_max_size)
 | 
			
		||||
@@ -101,9 +110,14 @@ void ConcurrentTask::startNext()
 | 
			
		||||
    setStepStatus(next->isMultiStep() ? next->getStepStatus() : next->getStatus());
 | 
			
		||||
    updateState();
 | 
			
		||||
 | 
			
		||||
    QCoreApplication::processEvents();
 | 
			
		||||
    QMetaObject::invokeMethod(next.get(), &Task::start, Qt::QueuedConnection);
 | 
			
		||||
 | 
			
		||||
    next->start();
 | 
			
		||||
    // Allow going up the number of concurrent tasks in case of tasks being added in the middle of a running task.
 | 
			
		||||
    int num_starts = m_total_max_size - m_doing.size();
 | 
			
		||||
    for (int i = 0; i < num_starts; i++)
 | 
			
		||||
        QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection);
 | 
			
		||||
 | 
			
		||||
    QCoreApplication::processEvents();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
 | 
			
		||||
@@ -145,7 +159,7 @@ void ConcurrentTask::subTaskProgress(qint64 current, qint64 total)
 | 
			
		||||
 | 
			
		||||
void ConcurrentTask::updateState()
 | 
			
		||||
{
 | 
			
		||||
    setProgress(m_done.count(), m_total_size);
 | 
			
		||||
    setProgress(m_done.count(), totalSize());
 | 
			
		||||
    setStatus(tr("Executing %1 task(s) (%2 out of %3 are done)")
 | 
			
		||||
                  .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(m_total_size)));
 | 
			
		||||
                  .arg(QString::number(m_doing.count()), QString::number(m_done.count()), QString::number(totalSize())));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,11 @@ public:
 | 
			
		||||
public slots:
 | 
			
		||||
    bool abort() override;
 | 
			
		||||
 | 
			
		||||
    /** Resets the internal state of the task.
 | 
			
		||||
     *  This allows the same task to be re-used.
 | 
			
		||||
     */
 | 
			
		||||
    void clear();
 | 
			
		||||
 | 
			
		||||
protected
 | 
			
		||||
slots:
 | 
			
		||||
    void executeTask() override;
 | 
			
		||||
@@ -36,6 +41,9 @@ slots:
 | 
			
		||||
    void subTaskProgress(qint64 current, qint64 total);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    // NOTE: This is not thread-safe.
 | 
			
		||||
    [[nodiscard]] unsigned int totalSize() const { return m_queue.size() + m_doing.size() + m_done.size(); }
 | 
			
		||||
 | 
			
		||||
    void setStepStatus(QString status) { m_step_status = status; emit stepStatus(status); };
 | 
			
		||||
 | 
			
		||||
    virtual void updateState();
 | 
			
		||||
@@ -51,7 +59,6 @@ protected:
 | 
			
		||||
    QHash<Task*, Task::Ptr> m_failed;
 | 
			
		||||
 | 
			
		||||
    int m_total_max_size;
 | 
			
		||||
    int m_total_size;
 | 
			
		||||
 | 
			
		||||
    qint64 m_stepProgress = 0;
 | 
			
		||||
    qint64 m_stepTotalProgress = 100;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,6 @@ void MultipleOptionsTask::startNext()
 | 
			
		||||
 | 
			
		||||
void MultipleOptionsTask::updateState()
 | 
			
		||||
{
 | 
			
		||||
    setProgress(m_done.count(), m_total_size);
 | 
			
		||||
    setStatus(tr("Attempting task %1 out of %2").arg(QString::number(m_doing.count() + m_done.count()), QString::number(m_total_size)));
 | 
			
		||||
    setProgress(m_done.count(), totalSize());
 | 
			
		||||
    setStatus(tr("Attempting task %1 out of %2").arg(QString::number(m_doing.count() + m_done.count()), QString::number(totalSize())));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,6 @@ void SequentialTask::startNext()
 | 
			
		||||
 | 
			
		||||
void SequentialTask::updateState()
 | 
			
		||||
{
 | 
			
		||||
    setProgress(m_done.count(), m_total_size);
 | 
			
		||||
    setStatus(tr("Executing task %1 out of %2").arg(QString::number(m_doing.count() + m_done.count()), QString::number(m_total_size)));
 | 
			
		||||
    setProgress(m_done.count(), totalSize());
 | 
			
		||||
    setStatus(tr("Executing task %1 out of %2").arg(QString::number(m_doing.count() + m_done.count()), QString::number(totalSize())));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user