mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-21 19:18:39 -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;
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -88,20 +92,36 @@ bool DownloadManager::downloadingFunctionalityAvailable() const
|
||||
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()
|
||||
{
|
||||
// so that DownloadInfo can be copied across threads
|
||||
qRegisterMetaType<DownloadInfo>("DownloadInfo");
|
||||
|
||||
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() ) {
|
||||
updateDownload(bookId);
|
||||
m_requestQueue.enqueue(bookId);
|
||||
}
|
||||
QThread::msleep(1000);
|
||||
}
|
||||
});
|
||||
mp_downloadUpdaterThread->start();
|
||||
timer->start(1000);
|
||||
}
|
||||
|
||||
void DownloadManager::restoreDownloads()
|
||||
|
@ -5,8 +5,10 @@
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QQueue>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
@ -17,6 +19,38 @@
|
||||
|
||||
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
|
||||
{
|
||||
public: // types
|
||||
@ -114,7 +148,11 @@ signals:
|
||||
void downloadUpdated(QString bookId, const DownloadInfo& );
|
||||
void downloadDisappeared(QString bookId);
|
||||
|
||||
private: // types
|
||||
typedef ThreadSafeQueue<QString> RequestQueue;
|
||||
|
||||
private: // functions
|
||||
void processDownloadActions();
|
||||
void updateDownload(QString bookId);
|
||||
|
||||
private: // data
|
||||
@ -122,6 +160,7 @@ private: // data
|
||||
kiwix::Downloader* const mp_downloader;
|
||||
Downloads m_downloads;
|
||||
QThread* mp_downloadUpdaterThread = nullptr;
|
||||
RequestQueue m_requestQueue;
|
||||
};
|
||||
|
||||
#endif // DOWNLOADMANAGEMENT_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user