ThreadWeaver

job.h
1 /* -*- C++ -*-
2  This file declares the Job class.
3 
4  SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <[email protected]>
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 namespace ThreadWeaver
22 {
23 namespace Private
24 {
25 class Job_Private;
26 }
27 
28 class Thread;
29 class QueuePolicy;
30 class QueueAPI;
31 class 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  */
46 class THREADWEAVER_EXPORT Job : public JobInterface
47 {
48 public:
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. Please note that the default implementation of
117  * the method does nothing (!). This is due to the fact that there is no generic method to abort a processing Job. Not even a
118  * default boolean flag makes sense, as Job could, for example, be in an event loop and will need to create an exit event. You
119  * have to reimplement the method to actually initiate an abort action.
120  *
121  * The method is not pure virtual because users are not supposed to be forced to always implement requestAbort(). Also, this
122  * method is supposed to return immediately, not after the abort has completed. It requests the abort, the Job has to act on
123  * the request. */
124  void requestAbort() override
125  {
126  }
127 
128  /** The job is about to be added to the weaver's job queue.
129  *
130  * The job will be added right after this method finished. The default implementation does nothing. Use this method to, for
131  * example, queue sub-operations as jobs before the job itself is queued.
132  *
133  * Note: When this method is called, the associated Weaver object's thread holds a lock on the weaver's queue. Therefore, it
134  * is save to assume that recursive queueing is atomic from the queues perspective.
135  *
136  * @param api the QueueAPI object the job will be queued in */
137  void aboutToBeQueued(QueueAPI *api) override;
138 
139  /** Called from aboutToBeQueued() while the mutex is being held. */
140  void aboutToBeQueued_locked(QueueAPI *api) override;
141 
142  /** This Job is about the be dequeued from the weaver's job queue.
143  *
144  * The job will be removed from the queue right after this method returns. Use this method to dequeue, if necessary,
145  * sub-operations (jobs) that this job has enqueued.
146  *
147  * Note: When this method is called, the associated Weaver object's thread does hold a lock on the weaver's queue.
148  * Note: The default implementation does nothing.
149  *
150  * @param weaver the Weaver object from which the job will be dequeued */
151  void aboutToBeDequeued(QueueAPI *api) override;
152 
153  /** Called from aboutToBeDequeued() while the mutex is being held. */
154  void aboutToBeDequeued_locked(QueueAPI *api) override;
155 
156  /** Returns true if the jobs's execute method finished. */
157  bool isFinished() const override;
158 
159  /** Assign a queue policy.
160  *
161  * Queue Policies customize the queueing (running) behaviour of sets of jobs. Examples for queue policies are dependencies
162  * and resource restrictions. Every queue policy object can only be assigned once to a job, multiple assignments will be
163  * IGNORED. */
164  void assignQueuePolicy(QueuePolicy *) override;
165 
166  /** Remove a queue policy from this job. */
167  void removeQueuePolicy(QueuePolicy *) override;
168 
169  /** @brief Return the queue policies assigned to this Job. */
170  QList<QueuePolicy *> queuePolicies() const override;
171 
172  /** The mutex used to protect this job. */
173  QMutex *mutex() const override;
174 
175 private:
176  Private::Job_Private *d_;
177 
178 protected:
179  Private::Job_Private *d();
180  const Private::Job_Private *d() const;
181 
182  friend class Executor;
183  /** The method that actually performs the job.
184  *
185  * It is called from execute(). This method is the one to overload it with the job's task.
186  *
187  * The Job will be executed in the specified thread. thread may be zero, indicating that the job is being executed some
188  * other way (for example, synchronously by some other job). self specifies the job as the queue sees it. Whenever publishing
189  * information about the job to the outside world, for example by emitting signals, use self, not this. self is the reference
190  * counted object handled by the queue. Using it as signal parameters will amongst other things prevent thejob from being
191  * memory managed and deleted.
192  */
193  virtual void run(JobPointer self, Thread *thread) override = 0;
194 
195  /** @brief Perform standard tasks before starting the execution of a job.
196  *
197  * The default implementation is empty.
198  * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are
199  * decorated expose the decorator's address, not the address of the decorated object. */
200  void defaultBegin(const JobPointer &job, Thread *thread) override;
201 
202  /** @brief Perform standard task after the execution of a job.
203  *
204  * The default implementation is empty.
205  * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are
206  * decorated expose the decorator's address, not the address of the decorated object. */
207  void defaultEnd(const JobPointer &job, Thread *thread) override;
208 };
209 
210 }
211 
212 #endif // THREADWEAVER_JOB_H
Q_SCRIPTABLE CaptureState status()
void requestAbort() override
Abort the execution of the job.
Definition: job.h:124
A Job is a simple abstraction of an action that is to be executed in a thread context.
Definition: job.h:46
QueuePolicy is an interface for customizations of the queueing behaviour of jobs.
Definition: queuepolicy.h:38
Thread represents a worker thread in a Queue's inventory.
Definition: thread.h:27
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:09:38 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.