mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-22 11:37:56 -04:00
Download updater thread works via a queue
Made the download updater thread process requests from a queue. Such a scheme paves the path to performing all download actions asynchronously by placing them onto the queue (which will eliminate non-responsiveness of the application when those commands hit the problem with slow responses from aria2c).
This commit is contained in:
parent
03c45e814b
commit
9defd359a6
@ -79,6 +79,10 @@ DownloadManager::~DownloadManager()
|
|||||||
{
|
{
|
||||||
QThread* t = mp_downloadUpdaterThread;
|
QThread* t = mp_downloadUpdaterThread;
|
||||||
mp_downloadUpdaterThread = nullptr; // tell the thread to terminate
|
mp_downloadUpdaterThread = nullptr; // tell the thread to terminate
|
||||||
|
|
||||||
|
// At this point the thread may be stuck waiting for data.
|
||||||
|
// Let's wake it up.
|
||||||
|
m_requestQueue.enqueue("");
|
||||||
t->wait();
|
t->wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,20 +92,36 @@ bool DownloadManager::downloadingFunctionalityAvailable() const
|
|||||||
return mp_downloader != nullptr;
|
return mp_downloader != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DownloadManager::processDownloadActions()
|
||||||
|
{
|
||||||
|
while ( mp_downloadUpdaterThread != nullptr ) {
|
||||||
|
const QString bookId = m_requestQueue.dequeue();
|
||||||
|
if ( !bookId.isEmpty() ) {
|
||||||
|
updateDownload(bookId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DownloadManager::startDownloadUpdaterThread()
|
void DownloadManager::startDownloadUpdaterThread()
|
||||||
{
|
{
|
||||||
// so that DownloadInfo can be copied across threads
|
// so that DownloadInfo can be copied across threads
|
||||||
qRegisterMetaType<DownloadInfo>("DownloadInfo");
|
qRegisterMetaType<DownloadInfo>("DownloadInfo");
|
||||||
|
|
||||||
mp_downloadUpdaterThread = QThread::create([=]() {
|
mp_downloadUpdaterThread = QThread::create([=]() {
|
||||||
while ( mp_downloadUpdaterThread != nullptr ) {
|
processDownloadActions();
|
||||||
|
});
|
||||||
|
|
||||||
|
mp_downloadUpdaterThread->start();
|
||||||
|
|
||||||
|
QTimer *timer = new QTimer(this);
|
||||||
|
connect(timer, &QTimer::timeout, [this]() {
|
||||||
|
if ( m_requestQueue.isEmpty() ) {
|
||||||
for ( const auto& bookId : m_downloads.keys() ) {
|
for ( const auto& bookId : m_downloads.keys() ) {
|
||||||
updateDownload(bookId);
|
m_requestQueue.enqueue(bookId);
|
||||||
}
|
}
|
||||||
QThread::msleep(1000);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mp_downloadUpdaterThread->start();
|
timer->start(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadManager::restoreDownloads()
|
void DownloadManager::restoreDownloads()
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
|
#include <QQueue>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -17,6 +19,38 @@
|
|||||||
|
|
||||||
typedef QMap<QString, QVariant> DownloadInfo;
|
typedef QMap<QString, QVariant> DownloadInfo;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class ThreadSafeQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void enqueue(const T& x)
|
||||||
|
{
|
||||||
|
const QMutexLocker threadSafetyGuarantee(&m_mutex);
|
||||||
|
m_queue.enqueue(x);
|
||||||
|
m_queueIsNotEmpty.wakeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
T dequeue()
|
||||||
|
{
|
||||||
|
const QMutexLocker threadSafetyGuarantee(&m_mutex);
|
||||||
|
if ( m_queue.isEmpty() )
|
||||||
|
m_queueIsNotEmpty.wait(&m_mutex);
|
||||||
|
|
||||||
|
return m_queue.dequeue();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
const QMutexLocker threadSafetyGuarantee(&m_mutex);
|
||||||
|
return m_queue.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private: // data
|
||||||
|
mutable QMutex m_mutex;
|
||||||
|
QQueue<T> m_queue;
|
||||||
|
QWaitCondition m_queueIsNotEmpty;
|
||||||
|
};
|
||||||
|
|
||||||
class DownloadState
|
class DownloadState
|
||||||
{
|
{
|
||||||
public: // types
|
public: // types
|
||||||
@ -114,7 +148,11 @@ signals:
|
|||||||
void downloadUpdated(QString bookId, const DownloadInfo& );
|
void downloadUpdated(QString bookId, const DownloadInfo& );
|
||||||
void downloadDisappeared(QString bookId);
|
void downloadDisappeared(QString bookId);
|
||||||
|
|
||||||
|
private: // types
|
||||||
|
typedef ThreadSafeQueue<QString> RequestQueue;
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
|
void processDownloadActions();
|
||||||
void updateDownload(QString bookId);
|
void updateDownload(QString bookId);
|
||||||
|
|
||||||
private: // data
|
private: // data
|
||||||
@ -122,6 +160,7 @@ private: // data
|
|||||||
kiwix::Downloader* const mp_downloader;
|
kiwix::Downloader* const mp_downloader;
|
||||||
Downloads m_downloads;
|
Downloads m_downloads;
|
||||||
QThread* mp_downloadUpdaterThread = nullptr;
|
QThread* mp_downloadUpdaterThread = nullptr;
|
||||||
|
RequestQueue m_requestQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DOWNLOADMANAGEMENT_H
|
#endif // DOWNLOADMANAGEMENT_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user