1 | /* -*- C++ -*- |
2 | This file declares the Job class. |
3 | |
4 | SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | |
8 | $Id: Job.h 32 2005-08-17 08:38:01Z mirko $ |
9 | */ |
10 | |
11 | #ifndef THREADWEAVER_JOB_H |
12 | #define THREADWEAVER_JOB_H |
13 | |
14 | #include "jobinterface.h" |
15 | #include "jobpointer.h" |
16 | #include "threadweaver_export.h" |
17 | |
18 | class QMutex; |
19 | class QWaitCondition; |
20 | |
21 | /*! |
22 | * \namespace ThreadWeaver |
23 | * \inmodule ThreadWeaver |
24 | */ |
25 | namespace ThreadWeaver |
26 | { |
27 | |
28 | /*! |
29 | * \namespace ThreadWeaver::Private |
30 | * \inmodule ThreadWeaver |
31 | */ |
32 | namespace Private |
33 | { |
34 | class Job_Private; |
35 | } |
36 | |
37 | class Thread; |
38 | class QueuePolicy; |
39 | class QueueAPI; |
40 | class Executor; |
41 | |
42 | /*! |
43 | * \class ThreadWeaver::Private::Job |
44 | * |
45 | * \inmodule ThreadWeaver |
46 | * |
47 | * \brief A Job is a simple abstraction of an action that is to be executed in a thread context. |
48 | * |
49 | * It is essential for the ThreadWeaver library that as a kind of convention, the different creators of Job objects do not touch |
50 | * the protected data members of the Job until somehow notified by the Job. |
51 | * |
52 | * Jobs may not be executed twice. Create two different objects to perform two consecutive or parallel runs. |
53 | * (\note this rule is being reconsidered). |
54 | * |
55 | * Jobs may declare dependencies. If Job B depends on Job A, B may not be executed before A is finished. To learn about |
56 | * dependencies, see DependencyPolicy. |
57 | * |
58 | * Job objects do not inherit QObject. To connect to signals when jobs are started or finished, see QObjectDecorator. |
59 | */ |
60 | class THREADWEAVER_EXPORT Job : public JobInterface |
61 | { |
62 | public: |
63 | /*! Construct a Job. */ |
64 | Job(); |
65 | /*! |
66 | */ |
67 | Job(Private::Job_Private *d); |
68 | |
69 | /*! Destructor. */ |
70 | ~Job() override; |
71 | |
72 | /*! Perform the job. The thread in which this job is executed is given as a parameter. |
73 | * |
74 | * Do not overload this method to create your own Job implementation, overload run(). |
75 | * Whenever the currently executed job is communicated to the outside world, use the supplied job pointer |
76 | * to keep the reference count correct. |
77 | * |
78 | * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are |
79 | * decorated expose the decorator's address, not the address of the decorated object. |
80 | */ |
81 | void execute(const JobPointer &job, Thread *) override; |
82 | |
83 | /*! Perform the job synchronously in the current thread. */ |
84 | void blockingExecute() override; |
85 | |
86 | /*! Set the Executor object that is supposed to run the job. |
87 | * |
88 | * Returns the previously set executor. The executor can never be unset. If zero is passed in as the new executor, the Job |
89 | * will internally reset to a default executor that only invokes run(). |
90 | */ |
91 | Executor *setExecutor(Executor *executor) override; |
92 | |
93 | /*! Returns the executor currently set on the Job. */ |
94 | Executor *executor() const override; |
95 | |
96 | /*! The queueing priority of the job. |
97 | * Jobs will be sorted by their queueing priority when enqueued. A higher queueing priority will place the job in front of all |
98 | * lower-priority jobs in the queue. |
99 | * |
100 | * \note A higher or lower priority does not influence queue policies. For example, a high-priority job that has an unresolved |
101 | * dependency will not be executed, which means an available lower-priority job will take precedence. |
102 | * |
103 | * The default implementation returns zero. Only if this method is overloaded for some job classes, priorities will influence |
104 | * the execution order of jobs. */ |
105 | int priority() const override; |
106 | |
107 | /*! \brief Set the status of the Job. |
108 | * |
109 | * Do not call this method unless you know what you are doing, please :-) . */ |
110 | void setStatus(Status) override; |
111 | |
112 | /*! \brief The status of the job. |
113 | * |
114 | * The status will be changed to Status_Success if the run() method exits normally. |
115 | */ |
116 | Status status() const override; |
117 | |
118 | /*! Return whether the Job finished successfully or not. |
119 | * The default implementation simply returns true. Overload in derived classes if the derived Job class can fail. |
120 | * |
121 | * If a job fails (success() returns false), it will *NOT* resolve its dependencies when it finishes. This will make sure that |
122 | * Jobs that depend on the failed job will not be started. |
123 | * |
124 | * There is an important gotcha: When a Job object it deleted, it will always resolve its dependencies. If dependent jobs should |
125 | * not be executed after a failure, it is important to dequeue those before deleting the failed Job. A Sequence may be |
126 | * helpful for that purpose. |
127 | */ |
128 | bool success() const override; |
129 | |
130 | /*! Abort the execution of the job. |
131 | * |
132 | * Call this method to ask the Job to abort if it is currently executed. Default implementation of the method sets a flag |
133 | * causing `shouldAbort()` return true. You can reimplement this method to actually initiate an abort action. |
134 | * |
135 | * This method is supposed to return immediately, not after the abort has completed. It requests the abort, the Job has to act on |
136 | * the request. */ |
137 | void requestAbort() override; |
138 | |
139 | /*! \brief Whether Job should abort itself |
140 | * |
141 | * It will return true if `requestAbort()` was invoked before |
142 | * but it's up to the job implementation itself to honor it |
143 | * and some implementations might not actually abort (ie. unabortable job). |
144 | * |
145 | * This function is threadsafe |
146 | * |
147 | * \since 6.0 |
148 | */ |
149 | bool shouldAbort() const; |
150 | |
151 | /*! The job is about to be added to the weaver's job queue. |
152 | * |
153 | * The job will be added right after this method finished. The default implementation does nothing. Use this method to, for |
154 | * example, queue sub-operations as jobs before the job itself is queued. |
155 | * |
156 | * \note When this method is called, the associated Weaver object's thread holds a lock on the weaver's queue. Therefore, it |
157 | * is save to assume that recursive queueing is atomic from the queues perspective. |
158 | * |
159 | * \a api the QueueAPI object the job will be queued in */ |
160 | void aboutToBeQueued(QueueAPI *api) override; |
161 | |
162 | /*! Called from aboutToBeQueued() while the mutex is being held. */ |
163 | void aboutToBeQueued_locked(QueueAPI *api) override; |
164 | |
165 | /*! This Job is about the be dequeued from the weaver's job queue. |
166 | * |
167 | * The job will be removed from the queue right after this method returns. Use this method to dequeue, if necessary, |
168 | * sub-operations (jobs) that this job has enqueued. |
169 | * |
170 | * \note When this method is called, the associated Weaver object's thread does hold a lock on the weaver's queue. |
171 | * \note The default implementation does nothing. |
172 | * |
173 | * \a weaver the Weaver object from which the job will be dequeued */ |
174 | void aboutToBeDequeued(QueueAPI *api) override; |
175 | |
176 | /*! Called from aboutToBeDequeued() while the mutex is being held. */ |
177 | void aboutToBeDequeued_locked(QueueAPI *api) override; |
178 | |
179 | /*! Returns true if the jobs's execute method finished. */ |
180 | bool isFinished() const override; |
181 | |
182 | /*! Add handler that will be invoked once job has finished |
183 | * |
184 | * \since 6.0 |
185 | */ |
186 | void onFinish(const std::function<void(const JobInterface &job)> &lambda); |
187 | |
188 | /*! Assign a queue policy. |
189 | * |
190 | * Queue Policies customize the queueing (running) behaviour of sets of jobs. Examples for queue policies are dependencies |
191 | * and resource restrictions. Every queue policy object can only be assigned once to a job, multiple assignments will be |
192 | * IGNORED. */ |
193 | void assignQueuePolicy(QueuePolicy *) override; |
194 | |
195 | /*! Remove a queue policy from this job. */ |
196 | void removeQueuePolicy(QueuePolicy *) override; |
197 | |
198 | /*! \brief Return the queue policies assigned to this Job. */ |
199 | QList<QueuePolicy *> queuePolicies() const override; |
200 | |
201 | /*! The mutex used to protect this job. */ |
202 | QMutex *mutex() const override; |
203 | |
204 | private: |
205 | Private::Job_Private *d_; |
206 | |
207 | protected: |
208 | /*! |
209 | */ |
210 | Private::Job_Private *d(); |
211 | /*! |
212 | */ |
213 | const Private::Job_Private *d() const; |
214 | |
215 | friend class Executor; |
216 | /*! The method that actually performs the job. |
217 | * |
218 | * It is called from execute(). This method is the one to overload it with the job's task. |
219 | * |
220 | * The Job will be executed in the specified thread. thread may be zero, indicating that the job is being executed some |
221 | * other way (for example, synchronously by some other job). self specifies the job as the queue sees it. Whenever publishing |
222 | * information about the job to the outside world, for example by emitting signals, use self, not this. self is the reference |
223 | * counted object handled by the queue. Using it as signal parameters will amongst other things prevent thejob from being |
224 | * memory managed and deleted. |
225 | */ |
226 | void run(JobPointer self, Thread *thread) override = 0; |
227 | |
228 | /*! \brief Perform standard tasks before starting the execution of a job. |
229 | * |
230 | * The default implementation is empty. |
231 | * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are |
232 | * decorated expose the decorator's address, not the address of the decorated object. */ |
233 | void defaultBegin(const JobPointer &job, Thread *thread) override; |
234 | |
235 | /*! \brief Perform standard task after the execution of a job. |
236 | * |
237 | * The default implementation is empty. |
238 | * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are |
239 | * decorated expose the decorator's address, not the address of the decorated object. */ |
240 | void defaultEnd(const JobPointer &job, Thread *thread) override; |
241 | }; |
242 | |
243 | } |
244 | |
245 | #endif // THREADWEAVER_JOB_H |
246 | |