KanoopCommonQt 2.1.1
Kanoop foundational Qt utility library
Loading...
Searching...
No Matches
abstractthreadclass.h
1/**
2 * @brief Abstract base class for QObject-based workers that run in a dedicated QThread.
3 */
4#ifndef ABSTRACTTHREADCLASS_H
5#define ABSTRACTTHREADCLASS_H
6
7#include <QMutex>
8#include <QObject>
9#include <QTextStream>
10#include <QThread>
11
12#include <Kanoop/mutexevent.h>
13#include <Kanoop/log.h>
14#include <Kanoop/kanoopcommon.h>
15
16#include "loggingbaseclass.h"
17
18/**
19 * @brief Manages the lifecycle of a QObject running in its own QThread.
20 *
21 * Subclass AbstractThreadClass and implement threadStarted() to perform work on the
22 * worker thread. The thread is created and destroyed automatically by start() and stop().
23 * The started() and finished() signals notify the main thread of state changes.
24 */
25class KANOOP_EXPORT AbstractThreadClass : public QObject,
26 public LoggingBaseClass
27{
28 Q_OBJECT
29
30public:
31 /**
32 * @brief Construct with an optional log category and parent.
33 * @param category Log category for this class (default: uncategorized)
34 * @param parent Optional QObject parent
35 */
36 AbstractThreadClass(const Log::LogCategory& category = Log::LogCategory(), QObject* parent = nullptr);
37
38 /**
39 * @brief Construct with a category name string and optional parent.
40 * @param category Category name string
41 * @param parent Optional QObject parent
42 */
43 AbstractThreadClass(const QString& category, QObject* parent = nullptr);
44
45 /** @brief Destructor — stops the thread if still running. */
47
48 /**
49 * @brief Start the worker thread and optionally wait for it to signal readiness.
50 * @param timeout How long to wait for the thread to start (zero = don't wait)
51 * @return true if the thread started successfully
52 */
53 virtual bool start(const TimeSpan& timeout = TimeSpan::zero());
54
55 /**
56 * @brief Request the worker thread to stop and optionally wait for it to finish.
57 * @param timeout How long to wait for the thread to finish (zero = don't wait)
58 * @return true if the thread stopped within the timeout
59 */
60 virtual bool stop(const TimeSpan &timeout = TimeSpan::zero());
61
62 /** @brief Immediately interrupt the worker thread (sets the stopping flag). */
63 virtual void abort();
64
65 /**
66 * @brief Block until the worker thread finishes or the timeout elapses.
67 * @param timeout Maximum wait duration (zero = wait indefinitely)
68 * @return true if the thread finished within the timeout
69 */
70 bool waitForCompletion(const TimeSpan& timeout = TimeSpan::zero());
71
72 /**
73 * @brief Test whether the worker thread is currently running.
74 * @return true if the thread is running
75 */
76 bool isRunning() const { return _thread.isRunning(); }
77
78 /**
79 * @brief Test whether stop() has been called and the thread is winding down.
80 * @return true if stopping is in progress
81 */
82 bool isStopping() const { return _stopping; }
83
84 /**
85 * @brief Return whether the last run completed successfully.
86 * @return true if finishAndStop() was called with success = true
87 */
88 bool success() const { return _success; }
89
90 /**
91 * @brief Return the completion message set by finishAndStop().
92 * @return Completion message string
93 */
94 QString completionMessage() const { return _message; }
95
96 /**
97 * @brief Control whether start() blocks until the thread signals readiness.
98 * @param value true to make start() blocking
99 */
100 void setBlockingStart(bool value) { _blockingStart = value; }
101
102protected:
103 /**
104 * @brief Entry point called on the worker thread immediately after it starts.
105 *
106 * Subclasses must implement this method to perform their work. When done,
107 * call finishAndStop() to signal completion.
108 */
109 virtual void threadStarted() = 0;
110
111 /** @brief Called on the worker thread just before it exits. */
112 virtual void threadFinished() {}
113
114 /**
115 * @brief Block until the thread has entered threadStarted() or the timeout elapses.
116 * @param timeout Maximum wait duration
117 * @return true if the thread started within the timeout
118 */
119 bool waitForStart(const TimeSpan& timeout);
120
121 /**
122 * @brief Signal that the worker has finished, recording success and a message.
123 * @param success Whether the work completed successfully
124 * @param message Optional human-readable completion message
125 */
126 void finishAndStop(bool success, const QString& message = QString());
127
128 /**
129 * @brief Write a line to the standard output stream.
130 * @param line Text to write
131 */
132 void writeLine(const QString& line) { _stdout << line << Qt::endl; }
133
134 /**
135 * @brief Write a line to the standard error stream.
136 * @param line Text to write
137 */
138 void writeErrorLine(const QString& line) { _stderr << line << Qt::endl; }
139
140private:
141 /** @brief Shared initialisation for all constructors. */
142 void commonInit();
143
144 bool _success = false;
145 QString _message;
146
147 bool _stopping = false;
148 bool _blockingStart = false;
149
150 QThread _thread;
151 QTextStream _stdout;
152 QTextStream _stderr;
153
154 MutexEvent _startEvent;
155 MutexEvent _stopEvent;
156
157signals:
158 /** @brief Emitted when the worker thread has started. */
159 void started();
160 /** @brief Emitted when the worker thread has finished. */
161 void finished();
162
163private slots:
164 /** @brief Invoked by QThread when the thread enters its event loop. */
165 void onThreadStarted();
166 /** @brief Invoked by QThread when the thread exits its event loop. */
167 void onThreadFinished();
168};
169
170#endif // ABSTRACTTHREADCLASS_H
Abstract base class for QObject-based workers that run in a dedicated QThread.
bool waitForCompletion(const TimeSpan &timeout=TimeSpan::zero())
Block until the worker thread finishes or the timeout elapses.
AbstractThreadClass(const QString &category, QObject *parent=nullptr)
Construct with a category name string and optional parent.
void setBlockingStart(bool value)
Control whether start() blocks until the thread signals readiness.
void finished()
Emitted when the worker thread has finished.
void writeLine(const QString &line)
Write a line to the standard output stream.
bool success() const
Return whether the last run completed successfully.
virtual void threadStarted()=0
Entry point called on the worker thread immediately after it starts.
virtual ~AbstractThreadClass()
Destructor — stops the thread if still running.
bool isRunning() const
Test whether the worker thread is currently running.
virtual bool start(const TimeSpan &timeout=TimeSpan::zero())
Start the worker thread and optionally wait for it to signal readiness.
void started()
Emitted when the worker thread has started.
bool waitForStart(const TimeSpan &timeout)
Block until the thread has entered threadStarted() or the timeout elapses.
bool isStopping() const
Test whether stop() has been called and the thread is winding down.
void finishAndStop(bool success, const QString &message=QString())
Signal that the worker has finished, recording success and a message.
virtual void abort()
Immediately interrupt the worker thread (sets the stopping flag).
QString completionMessage() const
Return the completion message set by finishAndStop().
virtual bool stop(const TimeSpan &timeout=TimeSpan::zero())
Request the worker thread to stop and optionally wait for it to finish.
AbstractThreadClass(const Log::LogCategory &category=Log::LogCategory(), QObject *parent=nullptr)
Construct with an optional log category and parent.
void writeErrorLine(const QString &line)
Write a line to the standard error stream.
virtual void threadFinished()
Called on the worker thread just before it exits.
A named logging category with an associated minimum log level.
Definition logcategory.h:34
Mixin base class providing categorized logging at four nesting levels.
MutexEvent.
Definition mutexevent.h:32
TimeSpan.
Definition timespan.h:42
static TimeSpan zero()
Return a zero-length TimeSpan.
Definition timespan.h:468