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
18class QMutex;
19class QWaitCondition;
20
21/*!
22 * \namespace ThreadWeaver
23 * \inmodule ThreadWeaver
24 */
25namespace ThreadWeaver
26{
27
28/*!
29 * \namespace ThreadWeaver::Private
30 * \inmodule ThreadWeaver
31 */
32namespace Private
33{
34class Job_Private;
35}
36
37class Thread;
38class QueuePolicy;
39class QueueAPI;
40class 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 */
60class THREADWEAVER_EXPORT Job : public JobInterface
61{
62public:
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
204private:
205 Private::Job_Private *d_;
206
207protected:
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

source code of threadweaver/src/job.h