Skip to content

Commit

Permalink
Use QThreadPool for torrent creation
Browse files Browse the repository at this point in the history
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 qbittorrent#19500.
  • Loading branch information
rcarpa authored and Radu Carpa committed Dec 1, 2023
1 parent 56c0b37 commit 46667e2
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ add_library(qbt_base STATIC
bittorrent/torrent.h
bittorrent/torrentcontenthandler.h
bittorrent/torrentcontentlayout.h
bittorrent/torrentcreatorthread.h
bittorrent/torrentcreator.h
bittorrent/torrentdescriptor.h
bittorrent/torrentimpl.h
bittorrent/torrentinfo.h
Expand Down Expand Up @@ -132,7 +132,7 @@ add_library(qbt_base STATIC
bittorrent/speedmonitor.cpp
bittorrent/torrent.cpp
bittorrent/torrentcontenthandler.cpp
bittorrent/torrentcreatorthread.cpp
bittorrent/torrentcreator.cpp
bittorrent/torrentdescriptor.cpp
bittorrent/torrentimpl.cpp
bittorrent/torrentinfo.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* exception statement from your version.
*/

#include "torrentcreatorthread.h"
#include "torrentcreator.h"

#include <fstream>

Expand Down Expand Up @@ -74,35 +74,34 @@ namespace

using namespace BitTorrent;

TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
: QThread(parent)
TorrentCreator::TorrentCreator(const TorrentCreatorParams &params, QObject *parent)
: QObject(parent)
, m_params {params}
{
}

TorrentCreatorThread::~TorrentCreatorThread()
void TorrentCreator::sendProgressSignal(int currentPieceIdx, int totalPieces)
{
requestInterruption();
wait();
emit updateProgress(static_cast<int>((currentPieceIdx * 100.) / totalPieces));
}

void TorrentCreatorThread::create(const TorrentCreatorParams &params)
void TorrentCreator::checkInterruptionRequested() const
{
m_params = params;
start();
if (isInterruptionRequested())
throw RuntimeError(tr("Operation aborted"));
}

void TorrentCreatorThread::sendProgressSignal(int currentPieceIdx, int totalPieces)
void TorrentCreator::requestInterruption()
{
emit updateProgress(static_cast<int>((currentPieceIdx * 100.) / totalPieces));
m_interruptionRequested.storeRelaxed(1);
}

void TorrentCreatorThread::checkInterruptionRequested() const
bool TorrentCreator::isInterruptionRequested() const
{
if (isInterruptionRequested())
throw RuntimeError(tr("Operation aborted"));
return m_interruptionRequested.loadRelaxed() != 0;
}

void TorrentCreatorThread::run()
void TorrentCreator::run()
{
emit updateProgress(0);

Expand Down Expand Up @@ -225,9 +224,9 @@ void TorrentCreatorThread::run()
}

#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
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
{
if (inputPath.isEmpty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@

#pragma once

#include <QAtomicInt>
#include <QObject>
#include <QRunnable>
#include <QStringList>
#include <QThread>

#include "base/path.h"

Expand Down Expand Up @@ -62,16 +64,20 @@ namespace BitTorrent
QStringList urlSeeds;
};

class TorrentCreatorThread final : public QThread
class TorrentCreator final : public QObject, public QRunnable
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(TorrentCreatorThread)
Q_DISABLE_COPY_MOVE(TorrentCreator)

public:
explicit TorrentCreatorThread(QObject *parent = nullptr);
~TorrentCreatorThread() override;
explicit TorrentCreator(const TorrentCreatorParams &params, QObject *parent = nullptr);

void create(const TorrentCreatorParams &params);
void run() override;

bool isInterruptionRequested() const;

public slots:
void requestInterruption();

#ifdef QBT_USES_LIBTORRENT2
static int calculateTotalPieces(const Path &inputPath, int pieceSize, TorrentFormat torrentFormat);
Expand All @@ -86,10 +92,10 @@ namespace BitTorrent
void updateProgress(int progress);

private:
void run() override;
void sendProgressSignal(int currentPieceIdx, int totalPieces);
void checkInterruptionRequested() const;

TorrentCreatorParams m_params;
QAtomicInt m_interruptionRequested;
};
}
22 changes: 13 additions & 9 deletions src/gui/torrentcreatordialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace
TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultPath)
: QDialog(parent)
, m_ui(new Ui::TorrentCreatorDialog)
, m_creatorThread(new BitTorrent::TorrentCreatorThread(this))
, m_threadPool(this)
, m_storeDialogSize(SETTINGS_KEY(u"Size"_s))
, m_storePieceSize(SETTINGS_KEY(u"PieceSize"_s))
, m_storePrivateTorrent(SETTINGS_KEY(u"PrivateTorrent"_s))
Expand Down Expand Up @@ -90,13 +90,11 @@ TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultP
connect(m_ui->buttonCalcTotalPieces, &QPushButton::clicked, this, &TorrentCreatorDialog::updatePiecesCount);
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();
updateInputPath(defaultPath);

m_threadPool.setMaxThreadCount(1);

#ifdef QBT_USES_LIBTORRENT2
m_ui->checkOptimizeAlignment->hide();
#else
Expand Down Expand Up @@ -233,8 +231,14 @@ void TorrentCreatorDialog::onCreateButtonClicked()
, m_ui->URLSeedsList->toPlainText().split(u'\n', Qt::SkipEmptyParts)
};

// run the creator thread
m_creatorThread->create(params);
auto *torrentCreator = new BitTorrent::TorrentCreator(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)
Expand Down Expand Up @@ -286,11 +290,11 @@ void TorrentCreatorDialog::updatePiecesCount()
{
const Path path = m_ui->textInputPath->selectedPath();
#ifdef QBT_USES_LIBTORRENT2
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(
const int count = BitTorrent::TorrentCreator::calculateTotalPieces(
path, getPieceSize(), getTorrentFormat());
#else
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path
const int count = BitTorrent::TorrentCreator::calculateTotalPieces(path
, getPieceSize(), isAlignmentOptimized, getPaddedFileSizeLimit());
#endif
m_ui->labelTotalPieces->setText(QString::number(count));
Expand Down
5 changes: 3 additions & 2 deletions src/gui/torrentcreatordialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@
#pragma once

#include <QDialog>
#include <QThreadPool>

#include "base/bittorrent/torrentcreatorthread.h"
#include "base/bittorrent/torrentcreator.h"
#include "base/path.h"
#include "base/settingvalue.h"

Expand Down Expand Up @@ -75,7 +76,7 @@ private slots:
#endif

Ui::TorrentCreatorDialog *m_ui = nullptr;
BitTorrent::TorrentCreatorThread *m_creatorThread = nullptr;
QThreadPool m_threadPool;

// settings
SettingValue<QSize> m_storeDialogSize;
Expand Down

0 comments on commit 46667e2

Please sign in to comment.