修复偶现的由于队列处理不当导致的搜索应用崩溃问题。

This commit is contained in:
iaom 2023-01-21 11:37:39 +08:00
parent 4fdc102102
commit a6a5b7846a
6 changed files with 63 additions and 56 deletions

View File

@ -23,21 +23,21 @@
using namespace UkuiSearch; using namespace UkuiSearch;
SearchResultManager::SearchResultManager(const QString& plugin_id, QObject *parent) : QObject(parent) SearchResultManager::SearchResultManager(const QString& plugin_id, QObject *parent) : QObject(parent)
{ {
m_plugin_id = plugin_id; m_pluginId = plugin_id;
m_result_queue = new DataQueue<SearchPluginIface::ResultInfo>; m_resultQueue = new DataQueue<SearchPluginIface::ResultInfo>;
m_get_result_thread = new ReceiveResultThread(m_result_queue, this); m_getResultThread = new ReceiveResultThread(m_resultQueue, this);
initConnections(); initConnections();
} }
void SearchResultManager::startSearch(const QString &keyword) void SearchResultManager::startSearch(const QString &keyword)
{ {
qDebug()<<m_plugin_id<<"started"; qDebug()<<m_pluginId<<"started";
if(! m_get_result_thread->isRunning()) { if(! m_getResultThread->isRunning()) {
m_get_result_thread->start(); m_getResultThread->start();
} }
m_result_queue->clear(); m_resultQueue->clear();
SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_plugin_id); SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_pluginId);
plugin->KeywordSearch(keyword, m_result_queue); plugin->KeywordSearch(keyword, m_resultQueue);
} }
/** /**
@ -45,54 +45,49 @@ void SearchResultManager::startSearch(const QString &keyword)
*/ */
void SearchResultManager::stopSearch() void SearchResultManager::stopSearch()
{ {
if(m_get_result_thread->isRunning()) { if(m_getResultThread->isRunning()) {
qDebug()<<m_plugin_id<<"stopped"; m_getResultThread->stop();
m_get_result_thread->stop(); SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_pluginId);
SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_plugin_id);
plugin->stopSearch(); plugin->stopSearch();
// m_get_result_thread->quit(); qDebug() << m_pluginId << "stopped";
} }
} }
void SearchResultManager::initConnections() void SearchResultManager::initConnections()
{ {
connect(m_get_result_thread, &ReceiveResultThread::gotResultInfo, this, &SearchResultManager::gotResultInfo); connect(m_getResultThread, &ReceiveResultThread::gotResultInfo, this, &SearchResultManager::gotResultInfo);
} }
ReceiveResultThread::ReceiveResultThread(DataQueue<SearchPluginIface::ResultInfo> * result_queue, QObject *parent) ReceiveResultThread::ReceiveResultThread(DataQueue<SearchPluginIface::ResultInfo> * resultQueue, QObject *parent): QThread(parent)
{ {
m_result_queue = result_queue; m_resultQueue = resultQueue;
} }
void ReceiveResultThread::stop() void ReceiveResultThread::stop()
{ {
this->requestInterruption(); this->requestInterruption();
this->wait(); this->wait();
this->quit();
} }
void ReceiveResultThread::run() void ReceiveResultThread::run()
{ {
QTimer *m_timer = new QTimer; QTimer *timer = new QTimer;
m_timer->setInterval(3000); timer->setInterval(3000);
bool is_empty;
while(!isInterruptionRequested()) {
is_empty = false;
if(!m_result_queue->isEmpty()) {
Q_EMIT this->gotResultInfo(m_result_queue->dequeue());
} else { while(!isInterruptionRequested()) {
is_empty = true; SearchPluginIface::ResultInfo oneResult = m_resultQueue->tryDequeue();
if(oneResult.name.isEmpty()) {
if(!timer->isActive()) {
timer->start();
} }
if(m_timer->isActive() && m_timer->remainingTime() < 0.01) {
this->requestInterruption();
}
if(is_empty && !m_timer->isActive()) {
m_timer->start();
} else if(!is_empty) {
m_timer->stop();
} else {
msleep(100); msleep(100);
} else {
timer->stop();
Q_EMIT gotResultInfo(oneResult);
}
if(timer->isActive() && timer->remainingTime() < 0.01 && m_resultQueue->isEmpty()) {
this->requestInterruption();
} }
} }
delete m_timer; delete m_timer;

View File

@ -25,21 +25,22 @@
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
#include <QDebug> #include <QDebug>
#include "pluginmanage/search-plugin-manager.h" #include "search-plugin-manager.h"
namespace UkuiSearch { namespace UkuiSearch {
class ReceiveResultThread : public QThread { class ReceiveResultThread : public QThread {
Q_OBJECT Q_OBJECT
public: public:
ReceiveResultThread(DataQueue<SearchPluginIface::ResultInfo> * result_queue, QObject * parent = nullptr); ReceiveResultThread(DataQueue<SearchPluginIface::ResultInfo> * resultQueue, QObject * parent = nullptr);
~ReceiveResultThread() = default; ~ReceiveResultThread() = default;
void stop(); void stop();
protected: protected:
void run() override; void run() override;
private: private:
DataQueue<SearchPluginIface::ResultInfo> * m_result_queue; DataQueue<SearchPluginIface::ResultInfo> * m_resultQueue;
QTimer *m_timer = nullptr;
Q_SIGNALS: Q_SIGNALS:
void gotResultInfo(const SearchPluginIface::ResultInfo&); void gotResultInfo(const SearchPluginIface::ResultInfo&);
@ -59,9 +60,9 @@ public Q_SLOTS:
private: private:
void initConnections(); void initConnections();
QString m_plugin_id; QString m_pluginId;
DataQueue<SearchPluginIface::ResultInfo> * m_result_queue; DataQueue<SearchPluginIface::ResultInfo> * m_resultQueue;
ReceiveResultThread * m_get_result_thread = nullptr; ReceiveResultThread * m_getResultThread = nullptr;
Q_SIGNALS: Q_SIGNALS:
void gotResultInfo(const SearchPluginIface::ResultInfo&); void gotResultInfo(const SearchPluginIface::ResultInfo&);

View File

@ -33,7 +33,6 @@ AppSearchPlugin::AppSearchPlugin(QObject *parent) : QThread(parent), m_appSearch
AppSearchPlugin::~AppSearchPlugin() AppSearchPlugin::~AppSearchPlugin()
{ {
this->quit();
this->wait(); this->wait();
if (m_timer) { if (m_timer) {
@ -161,17 +160,15 @@ QWidget *AppSearchPlugin::detailPage(const ResultInfo &ri)
void AppSearchPlugin::run() void AppSearchPlugin::run()
{ {
m_timer->setInterval(3000);
while(!isInterruptionRequested()) { while(!isInterruptionRequested()) {
if (m_appSearchResults->isEmpty()) { ResultItem oneResult = m_appSearchResults->tryDequeue();
if(oneResult.getSearchId() == 0 && oneResult.getItemKey().isEmpty() && oneResult.getExtral().isEmpty()) {
if(!m_timer->isActive()) { if(!m_timer->isActive()) {
m_timer->start(); m_timer->start();
} }
msleep(100);
} else { } else {
if (m_timer->isActive()) {
m_timer->stop(); m_timer->stop();
}
ResultItem oneResult = m_appSearchResults->dequeue();
SearchPluginIface::ResultInfo ri; SearchPluginIface::ResultInfo ri;
ri.actionKey = oneResult.getExtral().at(0).toString(); ri.actionKey = oneResult.getExtral().at(0).toString();
ri.name = oneResult.getExtral().at(1).toString(); ri.name = oneResult.getExtral().at(1).toString();
@ -184,12 +181,9 @@ void AppSearchPlugin::run()
m_searchResult->enqueue(ri); m_searchResult->enqueue(ri);
} }
if (m_timer->isActive() && m_timer->remainingTime() < 0.01) { if(m_timer->isActive() && m_timer->remainingTime() < 0.01 && m_appSearchResults->isEmpty()) {
m_timer->setInterval(3000);
this->requestInterruption(); this->requestInterruption();
} }
msleep(100);
} }
} }

View File

@ -27,6 +27,14 @@ public:
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
return QList<T>::isEmpty(); return QList<T>::isEmpty();
} }
inline T tryDequeue() {
QMutexLocker locker(&m_mutex);
if(QList<T>::isEmpty()) {
return T();
} else {
return QList<T>::takeFirst();
}
}
private: private:
QMutex m_mutex; QMutex m_mutex;
}; };

View File

@ -42,6 +42,15 @@ public:
QVector<DescriptionInfo> description; QVector<DescriptionInfo> description;
QString actionKey; QString actionKey;
int type; int type;
ResultInfo(const QIcon &iconToSet = QIcon(), const QString &nameToSet = QString(),
const QVector<DescriptionInfo> &descriptionToSet = QVector<DescriptionInfo>(),
const QString &actionKeyToSet = QString(), const int &typeToSet = 0) {
icon = iconToSet;
name = nameToSet;
description = descriptionToSet;
actionKey = actionKeyToSet;
type = typeToSet;
}
}; };
virtual ~SearchPluginIface() {} virtual ~SearchPluginIface() {}

View File

@ -16,7 +16,7 @@ public:
QVariantList getExtral(); QVariantList getExtral();
private: private:
size_t m_searchId; size_t m_searchId = 0;
QString m_itemKey; QString m_itemKey;
QVariantList m_extral; QVariantList m_extral;
//and something else... //and something else...