6 #ifndef SWIFT_MISC_WORKER_H
7 #define SWIFT_MISC_WORKER_H
14 #include <type_traits>
16 #include <QMetaObject>
19 #include <QMutexLocker>
53 std::atomic<void *> m_handle {
nullptr };
65 static const QStringList &getLogCategories();
69 template <
typename T,
typename F>
70 void then(T *context, F functor)
72 Q_ASSERT(context->thread() == QThread::currentThread());
73 QMutexLocker lock(&m_finishedMutex);
75 if (m_finished) { private_ns::invokeSlot(functor, context); }
83 QMutexLocker lock(&m_finishedMutex);
85 if (m_finished) { functor(); }
92 QMutexLocker lock(&m_finishedMutex);
101 QMutexLocker lock(&m_finishedMutex);
102 if (m_finished) { functor(); }
107 template <
typename F>
110 QMutexLocker lock(&m_finishedMutex);
111 if (!m_finished) { functor(); }
116 template <
typename F1,
typename F2>
119 QMutexLocker lock(&m_finishedMutex);
120 if (m_finished) { ifFunctor(); }
121 else { elseFunctor(); }
126 void waitForFinished() noexcept;
130 void abandon() noexcept;
133 void abandonAndWait() noexcept;
136 static const QSet<
CWorkerBase *> &allWorkers() {
return s_allWorkers; }
155 bool isAbandoned()
const;
166 QMutexLocker lock(&m_finishedMutex);
172 virtual void quit() noexcept {}
173 virtual void quitAndWait() noexcept { waitForFinished(); }
175 bool m_started =
false;
176 bool m_finished =
false;
177 mutable QRecursiveMutex m_finishedMutex;
178 static QSet<CWorkerBase *> s_allWorkers;
200 template <
typename F>
203 int typeId = qMetaTypeId<std::decay_t<decltype(std::forward<F>(task)())>>();
204 return fromTaskImpl(owner, name, typeId, [task = std::forward<F>(task)]()
mutable {
205 if constexpr (std::is_void_v<decltype(task())>)
210 else {
return QVariant::fromValue(std::move(task)()); }
217 template <
typename R,
typename F>
220 Q_ASSERT_X(m_result.canConvert<R>(), Q_FUNC_INFO,
"Type in thenWithResult must match return type of task");
221 then([
this, functor]() { functor(this->resultNoWait<R>()); });
227 template <
typename R,
typename T,
typename F>
230 Q_ASSERT_X(m_result.canConvert<R>(), Q_FUNC_INFO,
"Type in thenWithResult must match return type of task");
235 auto promise = std::make_shared<std::promise<R>>();
236 auto future = promise->get_future().share();
237 then([
this, promise]() { promise->set_value(this->resultNoWait<R>()); });
238 then(context, [context, functor, future]() { private_ns::invokeSlot(functor, context, future.get()); });
244 template <
typename R>
248 return this->resultNoWait<R>();
256 CWorker(
const std::function<QVariant()> &task) : m_task(task) {}
257 static CWorker *fromTaskImpl(QObject *owner,
const QString &name,
int typeId,
258 const std::function<QVariant()> &task);
260 template <
typename R>
263 Q_ASSERT(m_result.canConvert<R>());
264 return m_result.value<R>();
267 std::function<QVariant()> m_task;
287 void start(QThread::Priority priority = QThread::InheritPriority);
292 void quit() noexcept
final;
296 void quitAndWait() noexcept
final;
308 void startUpdating(
int updateTimeSecs);
314 const QObject *
owner()
const {
return m_owner; }
331 void stopUpdateTimer();
333 QTimer m_updateTimer {
this };
343 QObject *m_owner =
nullptr;
345 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.
void setEnabled(bool enabled)
Enabled (running)?
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.
Base class for CWorker and CContinuousWorker.
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.
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.