From 2a1541786ab963f73856b02600be379fd703c75e Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sun, 16 Nov 2014 01:08:27 +0000 Subject: [PATCH] refs #334 Added class CContinuousWorker, base class for long-lived threaded worker objects. Inherits from CWorkerBase. --- src/blackmisc/worker.cpp | 39 ++++++++++++++++++++++++++++++++++++ src/blackmisc/worker.h | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/blackmisc/worker.cpp b/src/blackmisc/worker.cpp index ed29ea299..3f026a8f4 100644 --- a/src/blackmisc/worker.cpp +++ b/src/blackmisc/worker.cpp @@ -40,4 +40,43 @@ namespace BlackMisc QMetaObject::invokeMethod(this, "deleteLater"); } + void CContinuousWorker::start(QThread::Priority priority) + { + if (m_name.isEmpty()) { m_name = metaObject()->className(); } + + auto *thread = new CRegularThread(m_owner); + + QString ownerName = m_owner->objectName().isEmpty() ? m_owner->metaObject()->className() : m_owner->objectName(); + thread->setObjectName(ownerName + ":" + m_name); + setObjectName(m_name); + + moveToThread(thread); + connect(thread, &QThread::started, this, &CContinuousWorker::initialize); + connect(thread, &QThread::finished, this, &CContinuousWorker::cleanup); + connect(thread, &QThread::finished, this, &CContinuousWorker::ps_finish); + thread->start(priority); + } + + void CContinuousWorker::quit() + { + thread()->quit(); + } + + void CContinuousWorker::quitAndWait() + { + auto *ownThread = thread(); + quit(); + ownThread->wait(); + } + + void CContinuousWorker::ps_finish() + { + setFinished(); + + auto *ownThread = thread(); + moveToThread(ownThread->thread()); // move worker back to the thread which constructed it, so there is no race on deletion + QMetaObject::invokeMethod(ownThread, "deleteLater"); + QMetaObject::invokeMethod(this, "deleteLater"); + } + } diff --git a/src/blackmisc/worker.h b/src/blackmisc/worker.h index 6ec9180cc..7d594c6ce 100644 --- a/src/blackmisc/worker.h +++ b/src/blackmisc/worker.h @@ -210,6 +210,49 @@ namespace BlackMisc std::function m_task; }; + /*! + * Base class for a long-lived worker object which lives in its own thread. + */ + class CContinuousWorker : public CWorkerBase + { + Q_OBJECT + + public: + /*! + * Constructor. + * \param owner Will be the parent of the new thread (the worker has no parent). + * \param name A name for the worker, which will be used to create a name for the thread. + */ + CContinuousWorker(QObject *owner, const QString &name = "") : m_owner(owner), m_name(name) {} + + //! Starts a thread and moves the worker into it. + void start(QThread::Priority priority = QThread::InheritPriority); + + //! Stops the thread the next time around its event loop. + //! The thread and the worker will then be deleted. + //! \threadsafe + void quit(); + + //! Calls quit() and blocks until the thread is finished. + //! \threadsafe Will deadlock if called by the worker thread. + void quitAndWait(); + + protected slots: + //! Called when the thread is started. + virtual void initialize() {} + + //! Called when the thread is finished. + virtual void cleanup() {} + + private slots: + //! Called after cleanup(). + void ps_finish(); + + private: + QObject *m_owner; + QString m_name; + }; + } #endif