ThreadWeaver

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

KDE's Doxygen guidelines are available online.