mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-25 18:56:34 +03:00
Use QThreadPool for torrent creation
The change is in preparation for adding the possibility to create torrent files via the API. Rework TorrentCreatorThread to be a more lightweight QRunnable class. The parameters are now defined on construction time and are fixed throughout the lifecycle of the TorrentCreator. The lifecycle of the object is not bound to the one of QDialog anymore; it is now handled by the QThreadPool. This will enable easier queueing of multiple torrent creation jobs without risk of spawning many threads. PR #19500.
This commit is contained in:
parent
9ab8203c8a
commit
bbac94cc95
5 changed files with 50 additions and 40 deletions
|
@ -35,7 +35,7 @@ add_library(qbt_base STATIC
|
||||||
bittorrent/torrent.h
|
bittorrent/torrent.h
|
||||||
bittorrent/torrentcontenthandler.h
|
bittorrent/torrentcontenthandler.h
|
||||||
bittorrent/torrentcontentlayout.h
|
bittorrent/torrentcontentlayout.h
|
||||||
bittorrent/torrentcreatorthread.h
|
bittorrent/torrentcreator.h
|
||||||
bittorrent/torrentdescriptor.h
|
bittorrent/torrentdescriptor.h
|
||||||
bittorrent/torrentimpl.h
|
bittorrent/torrentimpl.h
|
||||||
bittorrent/torrentinfo.h
|
bittorrent/torrentinfo.h
|
||||||
|
@ -132,7 +132,7 @@ add_library(qbt_base STATIC
|
||||||
bittorrent/speedmonitor.cpp
|
bittorrent/speedmonitor.cpp
|
||||||
bittorrent/torrent.cpp
|
bittorrent/torrent.cpp
|
||||||
bittorrent/torrentcontenthandler.cpp
|
bittorrent/torrentcontenthandler.cpp
|
||||||
bittorrent/torrentcreatorthread.cpp
|
bittorrent/torrentcreator.cpp
|
||||||
bittorrent/torrentdescriptor.cpp
|
bittorrent/torrentdescriptor.cpp
|
||||||
bittorrent/torrentimpl.cpp
|
bittorrent/torrentimpl.cpp
|
||||||
bittorrent/torrentinfo.cpp
|
bittorrent/torrentinfo.cpp
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "torrentcreatorthread.h"
|
#include "torrentcreator.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
@ -74,35 +74,34 @@ namespace
|
||||||
|
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
|
|
||||||
TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
|
TorrentCreator::TorrentCreator(const TorrentCreatorParams ¶ms, QObject *parent)
|
||||||
: QThread(parent)
|
: QObject(parent)
|
||||||
|
, m_params {params}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentCreatorThread::~TorrentCreatorThread()
|
void TorrentCreator::sendProgressSignal(int currentPieceIdx, int totalPieces)
|
||||||
{
|
|
||||||
requestInterruption();
|
|
||||||
wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentCreatorThread::create(const TorrentCreatorParams ¶ms)
|
|
||||||
{
|
|
||||||
m_params = params;
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentCreatorThread::sendProgressSignal(int currentPieceIdx, int totalPieces)
|
|
||||||
{
|
{
|
||||||
emit updateProgress(static_cast<int>((currentPieceIdx * 100.) / totalPieces));
|
emit updateProgress(static_cast<int>((currentPieceIdx * 100.) / totalPieces));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorThread::checkInterruptionRequested() const
|
void TorrentCreator::checkInterruptionRequested() const
|
||||||
{
|
{
|
||||||
if (isInterruptionRequested())
|
if (isInterruptionRequested())
|
||||||
throw RuntimeError(tr("Operation aborted"));
|
throw RuntimeError(tr("Operation aborted"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorThread::run()
|
void TorrentCreator::requestInterruption()
|
||||||
|
{
|
||||||
|
m_interruptionRequested.storeRelaxed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TorrentCreator::isInterruptionRequested() const
|
||||||
|
{
|
||||||
|
return m_interruptionRequested.loadRelaxed() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TorrentCreator::run()
|
||||||
{
|
{
|
||||||
emit updateProgress(0);
|
emit updateProgress(0);
|
||||||
|
|
||||||
|
@ -225,9 +224,9 @@ void TorrentCreatorThread::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QBT_USES_LIBTORRENT2
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
int TorrentCreatorThread::calculateTotalPieces(const Path &inputPath, const int pieceSize, const TorrentFormat torrentFormat)
|
int TorrentCreator::calculateTotalPieces(const Path &inputPath, const int pieceSize, const TorrentFormat torrentFormat)
|
||||||
#else
|
#else
|
||||||
int TorrentCreatorThread::calculateTotalPieces(const Path &inputPath, const int pieceSize, const bool isAlignmentOptimized, const int paddedFileSizeLimit)
|
int TorrentCreator::calculateTotalPieces(const Path &inputPath, const int pieceSize, const bool isAlignmentOptimized, const int paddedFileSizeLimit)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (inputPath.isEmpty())
|
if (inputPath.isEmpty())
|
|
@ -28,8 +28,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAtomicInt>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QRunnable>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
|
|
||||||
|
@ -62,16 +64,20 @@ namespace BitTorrent
|
||||||
QStringList urlSeeds;
|
QStringList urlSeeds;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TorrentCreatorThread final : public QThread
|
class TorrentCreator final : public QObject, public QRunnable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(TorrentCreatorThread)
|
Q_DISABLE_COPY_MOVE(TorrentCreator)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TorrentCreatorThread(QObject *parent = nullptr);
|
explicit TorrentCreator(const TorrentCreatorParams ¶ms, QObject *parent = nullptr);
|
||||||
~TorrentCreatorThread() override;
|
|
||||||
|
|
||||||
void create(const TorrentCreatorParams ¶ms);
|
void run() override;
|
||||||
|
|
||||||
|
bool isInterruptionRequested() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void requestInterruption();
|
||||||
|
|
||||||
#ifdef QBT_USES_LIBTORRENT2
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
static int calculateTotalPieces(const Path &inputPath, int pieceSize, TorrentFormat torrentFormat);
|
static int calculateTotalPieces(const Path &inputPath, int pieceSize, TorrentFormat torrentFormat);
|
||||||
|
@ -86,10 +92,10 @@ namespace BitTorrent
|
||||||
void updateProgress(int progress);
|
void updateProgress(int progress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void run() override;
|
|
||||||
void sendProgressSignal(int currentPieceIdx, int totalPieces);
|
void sendProgressSignal(int currentPieceIdx, int totalPieces);
|
||||||
void checkInterruptionRequested() const;
|
void checkInterruptionRequested() const;
|
||||||
|
|
||||||
TorrentCreatorParams m_params;
|
TorrentCreatorParams m_params;
|
||||||
|
QAtomicInt m_interruptionRequested;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -59,7 +59,7 @@ namespace
|
||||||
TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultPath)
|
TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultPath)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, m_ui(new Ui::TorrentCreatorDialog)
|
, m_ui(new Ui::TorrentCreatorDialog)
|
||||||
, m_creatorThread(new BitTorrent::TorrentCreatorThread(this))
|
, m_threadPool(this)
|
||||||
, m_storeDialogSize(SETTINGS_KEY(u"Size"_s))
|
, m_storeDialogSize(SETTINGS_KEY(u"Size"_s))
|
||||||
, m_storePieceSize(SETTINGS_KEY(u"PieceSize"_s))
|
, m_storePieceSize(SETTINGS_KEY(u"PieceSize"_s))
|
||||||
, m_storePrivateTorrent(SETTINGS_KEY(u"PrivateTorrent"_s))
|
, m_storePrivateTorrent(SETTINGS_KEY(u"PrivateTorrent"_s))
|
||||||
|
@ -90,13 +90,11 @@ TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultP
|
||||||
connect(m_ui->buttonCalcTotalPieces, &QPushButton::clicked, this, &TorrentCreatorDialog::updatePiecesCount);
|
connect(m_ui->buttonCalcTotalPieces, &QPushButton::clicked, this, &TorrentCreatorDialog::updatePiecesCount);
|
||||||
connect(m_ui->checkStartSeeding, &QCheckBox::clicked, m_ui->checkIgnoreShareLimits, &QWidget::setEnabled);
|
connect(m_ui->checkStartSeeding, &QCheckBox::clicked, m_ui->checkIgnoreShareLimits, &QWidget::setEnabled);
|
||||||
|
|
||||||
connect(m_creatorThread, &BitTorrent::TorrentCreatorThread::creationSuccess, this, &TorrentCreatorDialog::handleCreationSuccess);
|
|
||||||
connect(m_creatorThread, &BitTorrent::TorrentCreatorThread::creationFailure, this, &TorrentCreatorDialog::handleCreationFailure);
|
|
||||||
connect(m_creatorThread, &BitTorrent::TorrentCreatorThread::updateProgress, this, &TorrentCreatorDialog::updateProgressBar);
|
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
updateInputPath(defaultPath);
|
updateInputPath(defaultPath);
|
||||||
|
|
||||||
|
m_threadPool.setMaxThreadCount(1);
|
||||||
|
|
||||||
#ifdef QBT_USES_LIBTORRENT2
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
m_ui->checkOptimizeAlignment->hide();
|
m_ui->checkOptimizeAlignment->hide();
|
||||||
#else
|
#else
|
||||||
|
@ -233,8 +231,14 @@ void TorrentCreatorDialog::onCreateButtonClicked()
|
||||||
, m_ui->URLSeedsList->toPlainText().split(u'\n', Qt::SkipEmptyParts)
|
, m_ui->URLSeedsList->toPlainText().split(u'\n', Qt::SkipEmptyParts)
|
||||||
};
|
};
|
||||||
|
|
||||||
// run the creator thread
|
auto *torrentCreator = new BitTorrent::TorrentCreator(params);
|
||||||
m_creatorThread->create(params);
|
connect(this, &QDialog::rejected, torrentCreator, &BitTorrent::TorrentCreator::requestInterruption);
|
||||||
|
connect(torrentCreator, &BitTorrent::TorrentCreator::creationSuccess, this, &TorrentCreatorDialog::handleCreationSuccess);
|
||||||
|
connect(torrentCreator, &BitTorrent::TorrentCreator::creationFailure, this, &TorrentCreatorDialog::handleCreationFailure);
|
||||||
|
connect(torrentCreator, &BitTorrent::TorrentCreator::updateProgress, this, &TorrentCreatorDialog::updateProgressBar);
|
||||||
|
|
||||||
|
// run the torrentCreator in a thread
|
||||||
|
m_threadPool.start(torrentCreator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorDialog::handleCreationFailure(const QString &msg)
|
void TorrentCreatorDialog::handleCreationFailure(const QString &msg)
|
||||||
|
@ -286,11 +290,11 @@ void TorrentCreatorDialog::updatePiecesCount()
|
||||||
{
|
{
|
||||||
const Path path = m_ui->textInputPath->selectedPath();
|
const Path path = m_ui->textInputPath->selectedPath();
|
||||||
#ifdef QBT_USES_LIBTORRENT2
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(
|
const int count = BitTorrent::TorrentCreator::calculateTotalPieces(
|
||||||
path, getPieceSize(), getTorrentFormat());
|
path, getPieceSize(), getTorrentFormat());
|
||||||
#else
|
#else
|
||||||
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();
|
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();
|
||||||
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path
|
const int count = BitTorrent::TorrentCreator::calculateTotalPieces(path
|
||||||
, getPieceSize(), isAlignmentOptimized, getPaddedFileSizeLimit());
|
, getPieceSize(), isAlignmentOptimized, getPaddedFileSizeLimit());
|
||||||
#endif
|
#endif
|
||||||
m_ui->labelTotalPieces->setText(QString::number(count));
|
m_ui->labelTotalPieces->setText(QString::number(count));
|
||||||
|
|
|
@ -30,8 +30,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include "base/bittorrent/torrentcreatorthread.h"
|
#include "base/bittorrent/torrentcreator.h"
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
#include "base/settingvalue.h"
|
#include "base/settingvalue.h"
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ui::TorrentCreatorDialog *m_ui = nullptr;
|
Ui::TorrentCreatorDialog *m_ui = nullptr;
|
||||||
BitTorrent::TorrentCreatorThread *m_creatorThread = nullptr;
|
QThreadPool m_threadPool;
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
SettingValue<QSize> m_storeDialogSize;
|
SettingValue<QSize> m_storeDialogSize;
|
||||||
|
|
Loading…
Reference in a new issue