6 #ifndef SWIFT_MISC_WORKER_H
7 #define SWIFT_MISC_WORKER_H
14 #include <type_traits>
16 #include <QMetaObject>
19 #include <QMutexLocker>
65 std::atomic<void *> m_handle {
nullptr };
92 static const QStringList &getLogCategories();
96 template <
typename T,
typename F>
97 void then(T *context, F functor)
99 Q_ASSERT(context->thread() == QThread::currentThread());
100 QMutexLocker lock(&m_finishedMutex);
102 if (m_finished) { private_ns::invokeSlot(functor, context); }
107 template <
typename F>
110 QMutexLocker lock(&m_finishedMutex);
112 if (m_finished) { functor(); }
119 QMutexLocker lock(&m_finishedMutex);
125 template <
typename F>
128 QMutexLocker lock(&m_finishedMutex);
129 if (m_finished) { functor(); }
134 template <
typename F>
137 QMutexLocker lock(&m_finishedMutex);
138 if (!m_finished) { functor(); }
143 template <
typename F1,
typename F2>
146 QMutexLocker lock(&m_finishedMutex);
147 if (m_finished) { ifFunctor(); }
148 else { elseFunctor(); }
153 void waitForFinished() noexcept;
157 void abandon() noexcept;
160 void abandonAndWait() noexcept;
163 static const QSet<
CWorkerBase *> &allWorkers() {
return s_allWorkers; }
179 bool isAbandoned()
const;
190 QMutexLocker lock(&m_finishedMutex);
196 virtual void quit() noexcept {}
197 virtual void quitAndWait() noexcept { waitForFinished(); }
199 bool m_started =
false;
200 bool m_finished =
false;
201 mutable QRecursiveMutex m_finishedMutex;
202 static QSet<CWorkerBase *> s_allWorkers;
224 template <
typename F>
227 int typeId = qMetaTypeId<std::decay_t<decltype(std::forward<F>(task)())>>();
228 return fromTaskImpl(owner, name, typeId, [task = std::forward<F>(task)]()
mutable {
229 if constexpr (std::is_void_v<decltype(task())>)
234 else {
return QVariant::fromValue(std::move(task)()); }
241 template <
typename R,
typename F>
244 Q_ASSERT_X(m_result.canConvert<R>(), Q_FUNC_INFO,
"Type in thenWithResult must match return type of task");
245 then([
this, functor]() { functor(this->resultNoWait<R>()); });
251 template <
typename R,
typename T,
typename F>
254 Q_ASSERT_X(m_result.canConvert<R>(), Q_FUNC_INFO,
"Type in thenWithResult must match return type of task");
259 auto promise = std::make_shared<std::promise<R>>();
260 auto future = promise->get_future().share();
261 then([
this, promise]() { promise->set_value(this->resultNoWait<R>()); });
262 then(context, [context, functor, future]() { private_ns::invokeSlot(functor, context, future.get()); });
268 template <
typename R>
272 return this->resultNoWait<R>();
280 CWorker(
const std::function<QVariant()> &task) : m_task(task) {}
281 static CWorker *fromTaskImpl(QObject *owner,
const QString &name,
int typeId,
282 const std::function<QVariant()> &task);
284 template <
typename R>
287 Q_ASSERT(m_result.canConvert<R>());
288 return m_result.value<R>();
291 std::function<QVariant()> m_task;
311 void start(QThread::Priority priority = QThread::InheritPriority);
316 void quit() noexcept
final;
320 void quitAndWait() noexcept
final;
330 const QObject *
owner()
const {
return m_owner; }
352 void setEnabled(
bool enabled) { m_enabled = enabled; }
357 QObject *m_owner =
nullptr;
359 std::atomic<bool> m_enabled {
true };
Base class for a long-lived worker object which lives in its own thread.
virtual void beforeQuit() noexcept
Called before quit is called.
bool isEnabled() const
Enabled (running)?
const QObject * owner() const
Owner of the worker.
virtual void cleanup()
Called when the thread is finished.
virtual void initialize()
Called when the thread is started.
virtual unsigned long waitTimeoutMs() const
Wait time for quitAndWait, 0 means not waiting.
const QString & getName()
Name of the worker.
Just a subclass of QThread whose destructor waits for the thread to finish.
CRegularThread(QObject *parent=nullptr)
Constructor.
CRegularThread(CRegularThread &&)=delete
Move constructor.
CRegularThread(const CRegularThread &)=delete
Copy constructor.
CRegularThread & operator=(CRegularThread &&)=delete
Move assignment.
CRegularThread & operator=(const CRegularThread &)=delete
Copy assignment.
Base class for CWorker and CContinuousWorker.
CWorkerBase & operator=(CWorkerBase &&)=delete
Move assignment.
void doIfFinished(F functor) const
Executes some code (in the caller's thread) if the task has finished.
void aboutToStart()
Emitted when the task is about to start.
void then(T *context, F functor)
Connects to a functor or method which will be called when the task is finished.
void setStarted()
Mark the task as started.
CWorkerBase(const CWorkerBase &)=delete
Copy constructor.
CWorkerBase(CWorkerBase &&)=delete
Move constructor.
CWorkerBase & operator=(const CWorkerBase &)=delete
Copy assignment.
void finished()
Emitted when the task is finished.
void then(F functor)
Connects to a functor which will be called when the task is finished.
bool isFinished() const
Returns true if the task has finished.
void doIfNotFinished(F functor) const
Executes some code (in the caller's thread) if the task has not finished.
bool hasStarted() const
True if the worker has started.
void doIfFinishedElse(F1 ifFunctor, F2 elseFunctor) const
Executes some code (in the caller's thread) if the task has finished and some different code if it ha...
void setFinished()
Mark the task as finished.
Class for doing some arbitrary parcel of work in its own thread.
static CWorker * fromTask(QObject *owner, const QString &name, F &&task)
Returns a new worker object which lives in a new thread.
R result()
Returns the result of the task, waiting for it to finish if necessary.
void thenWithResult(T *context, F functor)
Connects to a functor or method to which will be passed the result when the task is finished.
void thenWithResult(F functor)
Connects to a functor to which will be passed the result when the task is finished.
Free functions in swift::misc.
#define SWIFT_MISC_EXPORT
Export a class or function from the library.