1
0
mirror of https://github.com/jaredtao/TaoQuick.git synced 2025-01-31 21:22:58 +08:00
TaoQuick/3rdparty/TaoCommon/Thread/threadworkercontroller.h

130 lines
4.1 KiB
C
Raw Normal View History

2020-06-30 00:34:25 +08:00
#pragma once
#include "taocommonglobal.h"
#include "threadcommon.h"
#include <QMap>
#include <QThread>
namespace TaoCommon
{
// 对Qt Worker-Controller 线程模型的简单封装,适合精确控制的任务。
// 用法: ThreadController::getInstance()->work(workCall, resultCall)
// workCall是在新线程中执行的任务resultCall是任务执行完成后回到调用线程中用来处理执行结果。
// work函数返回值为任务id。
// 取消任务用ThreadController::getInstance()->cancle(id)函数。
class ThreadWorker : public QObject
{
Q_OBJECT
public:
ThreadWorker(uint64_t id, const WorkCallback &workCall, QObject *parent = nullptr) : QObject(parent), m_id(id), m_workCall(workCall) {}
signals:
void workFinished(bool, uint64_t);
public slots:
void doWork()
{
bool ret = m_workCall();
emit workFinished(ret, m_id);
}
private:
const uint64_t m_id;
WorkCallback m_workCall;
};
class TAO_API ThreadController : public QObject
{
Q_OBJECT
public:
static ThreadController *getInstance()
{
static ThreadController controller;
return &controller;
}
~ThreadController()
{
for (auto k : m_threadMap.uniqueKeys())
{
if (m_threadMap.value(k)->isRunning())
{
m_threadMap.value(k)->quit();
m_threadMap.value(k)->wait();
}
}
qDeleteAll(m_threadMap);
m_threadMap.clear();
m_resultCallback.clear();
}
uint64_t work(const WorkCallback &workCall, const WorkResultCallback &resultCall)
{
QThread *thread = new QThread;
m_rollId++;
ThreadWorker *obj = new ThreadWorker(m_rollId, workCall);
m_threadMap[m_rollId] = thread;
m_resultCallback[m_rollId] = resultCall;
obj->moveToThread(thread);
connect(thread, &QThread::finished, obj, &QObject::deleteLater);
connect(thread, &QThread::started, obj, &ThreadWorker::doWork);
connect(obj, &ThreadWorker::workFinished, this, &ThreadController::onWorkFinished, Qt::QueuedConnection);
thread->start();
return m_rollId;
}
void cancle(uint64_t id)
{
auto it = m_threadMap.find(id);
if (it != m_threadMap.end())
{
if ((*it)->isRunning())
{
(*it)->terminate();
}
}
m_resultCallback.remove(id);
}
void quit(uint64_t id)
{
auto it = m_threadMap.find(id);
if (it != m_threadMap.end())
{
if ((*it)->isRunning())
{
(*it)->quit();
(*it)->wait();
(*it)->deleteLater();
}
}
m_resultCallback.remove(id);
}
QList<uint64_t> getAllWorkId() const
{
return m_threadMap.uniqueKeys();
}
protected slots :
void onWorkFinished(bool ok, uint64_t id)
{
auto it = m_threadMap.find(id);
if (it != m_threadMap.end())
{
if ((*it)->isRunning())
{
(*it)->quit();
(*it)->wait();
(*it)->deleteLater();
}
m_threadMap.remove(id);
}
auto caller = m_resultCallback.find(id);
if (caller != m_resultCallback.end())
{
(*caller)(ok);
m_resultCallback.remove(id);
}
}
protected:
ThreadController(QObject *parent = nullptr) : QObject(parent) {}
private:
uint64_t m_rollId = 0;
QMap<uint64_t, QThread *> m_threadMap;
QMap<uint64_t, WorkResultCallback> m_resultCallback;
};
} // namespace LCIM