File indexing completed on 2024-04-28 04:01:23
0001 /* -*- C++ -*- 0002 This file declares the Job class. 0003 0004 SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 0008 $Id: Job.h 32 2005-08-17 08:38:01Z mirko $ 0009 */ 0010 0011 #ifndef THREADWEAVER_JOB_H 0012 #define THREADWEAVER_JOB_H 0013 0014 #include "jobinterface.h" 0015 #include "jobpointer.h" 0016 #include "threadweaver_export.h" 0017 0018 class QMutex; 0019 class QWaitCondition; 0020 0021 namespace ThreadWeaver 0022 { 0023 namespace Private 0024 { 0025 class Job_Private; 0026 } 0027 0028 class Thread; 0029 class QueuePolicy; 0030 class QueueAPI; 0031 class Executor; 0032 0033 /** @brief A Job is a simple abstraction of an action that is to be executed in a thread context. 0034 * 0035 * It is essential for the ThreadWeaver library that as a kind of convention, the different creators of Job objects do not touch 0036 * the protected data members of the Job until somehow notified by the Job. 0037 * 0038 * Jobs may not be executed twice. Create two different objects to perform two consecutive or parallel runs. 0039 * (Note: this rule is being reconsidered.) 0040 * 0041 * Jobs may declare dependencies. If Job B depends on Job A, B may not be executed before A is finished. To learn about 0042 * dependencies, see DependencyPolicy. 0043 * 0044 * Job objects do not inherit QObject. To connect to signals when jobs are started or finished, see QObjectDecorator. 0045 */ 0046 class THREADWEAVER_EXPORT Job : public JobInterface 0047 { 0048 public: 0049 /** Construct a Job. */ 0050 Job(); 0051 Job(Private::Job_Private *d); 0052 0053 /** Destructor. */ 0054 ~Job() override; 0055 0056 /** Perform the job. The thread in which this job is executed is given as a parameter. 0057 * 0058 * Do not overload this method to create your own Job implementation, overload run(). 0059 * Whenever the currently executed job is communicated to the outside world, use the supplied job pointer 0060 * to keep the reference count correct. 0061 * 0062 * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are 0063 * decorated expose the decorator's address, not the address of the decorated object. 0064 */ 0065 void execute(const JobPointer &job, Thread *) override; 0066 0067 /** Perform the job synchronously in the current thread. */ 0068 void blockingExecute() override; 0069 0070 /** Set the Executor object that is supposed to run the job. 0071 * 0072 * Returns the previously set executor. The executor can never be unset. If zero is passed in as the new executor, the Job 0073 * will internally reset to a default executor that only invokes run(). 0074 */ 0075 Executor *setExecutor(Executor *executor) override; 0076 0077 /** Returns the executor currently set on the Job. */ 0078 Executor *executor() const override; 0079 0080 /** The queueing priority of the job. 0081 * Jobs will be sorted by their queueing priority when enqueued. A higher queueing priority will place the job in front of all 0082 * lower-priority jobs in the queue. 0083 * 0084 * Note: A higher or lower priority does not influence queue policies. For example, a high-priority job that has an unresolved 0085 * dependency will not be executed, which means an available lower-priority job will take precedence. 0086 * 0087 * The default implementation returns zero. Only if this method is overloaded for some job classes, priorities will influence 0088 * the execution order of jobs. */ 0089 int priority() const override; 0090 0091 /** @brief Set the status of the Job. 0092 * 0093 * Do not call this method unless you know what you are doing, please :-) */ 0094 void setStatus(Status) override; 0095 0096 /** @brief The status of the job. 0097 * 0098 * The status will be changed to Status_Success if the run() method exits normally. 0099 */ 0100 Status status() const override; 0101 0102 /** Return whether the Job finished successfully or not. 0103 * The default implementation simply returns true. Overload in derived classes if the derived Job class can fail. 0104 * 0105 * If a job fails (success() returns false), it will *NOT* resolve its dependencies when it finishes. This will make sure that 0106 * Jobs that depend on the failed job will not be started. 0107 * 0108 * There is an important gotcha: When a Job object it deleted, it will always resolve its dependencies. If dependent jobs should 0109 * not be executed after a failure, it is important to dequeue those before deleting the failed Job. A Sequence may be 0110 * helpful for that purpose. 0111 */ 0112 bool success() const override; 0113 0114 /** Abort the execution of the job. 0115 * 0116 * Call this method to ask the Job to abort if it is currently executed. Default implementation of the method sets a flag 0117 * causing `shouldAbort()` return true. You can reimplement this method to actually initiate an abort action. 0118 * 0119 * This method is supposed to return immediately, not after the abort has completed. It requests the abort, the Job has to act on 0120 * the request. */ 0121 void requestAbort() override; 0122 0123 /** @brief Whether Job should abort itself 0124 * 0125 * It will return true if `requestAbort()` was invoked before 0126 * but it's up to the job implementation itself to honor it 0127 * and some implementations might not actually abort (ie. unabortable job). 0128 * 0129 * @threadsafe 0130 * 0131 * @since 6.0 0132 */ 0133 bool shouldAbort() const; 0134 0135 /** The job is about to be added to the weaver's job queue. 0136 * 0137 * The job will be added right after this method finished. The default implementation does nothing. Use this method to, for 0138 * example, queue sub-operations as jobs before the job itself is queued. 0139 * 0140 * Note: When this method is called, the associated Weaver object's thread holds a lock on the weaver's queue. Therefore, it 0141 * is save to assume that recursive queueing is atomic from the queues perspective. 0142 * 0143 * @param api the QueueAPI object the job will be queued in */ 0144 void aboutToBeQueued(QueueAPI *api) override; 0145 0146 /** Called from aboutToBeQueued() while the mutex is being held. */ 0147 void aboutToBeQueued_locked(QueueAPI *api) override; 0148 0149 /** This Job is about the be dequeued from the weaver's job queue. 0150 * 0151 * The job will be removed from the queue right after this method returns. Use this method to dequeue, if necessary, 0152 * sub-operations (jobs) that this job has enqueued. 0153 * 0154 * Note: When this method is called, the associated Weaver object's thread does hold a lock on the weaver's queue. 0155 * Note: The default implementation does nothing. 0156 * 0157 * @param weaver the Weaver object from which the job will be dequeued */ 0158 void aboutToBeDequeued(QueueAPI *api) override; 0159 0160 /** Called from aboutToBeDequeued() while the mutex is being held. */ 0161 void aboutToBeDequeued_locked(QueueAPI *api) override; 0162 0163 /** Returns true if the jobs's execute method finished. */ 0164 bool isFinished() const override; 0165 0166 /** Add handler that will be invoked once job has finished 0167 * 0168 * @since 6.0 0169 */ 0170 void onFinish(const std::function<void(const JobInterface &job)> &lambda); 0171 0172 /** Assign a queue policy. 0173 * 0174 * Queue Policies customize the queueing (running) behaviour of sets of jobs. Examples for queue policies are dependencies 0175 * and resource restrictions. Every queue policy object can only be assigned once to a job, multiple assignments will be 0176 * IGNORED. */ 0177 void assignQueuePolicy(QueuePolicy *) override; 0178 0179 /** Remove a queue policy from this job. */ 0180 void removeQueuePolicy(QueuePolicy *) override; 0181 0182 /** @brief Return the queue policies assigned to this Job. */ 0183 QList<QueuePolicy *> queuePolicies() const override; 0184 0185 /** The mutex used to protect this job. */ 0186 QMutex *mutex() const override; 0187 0188 private: 0189 Private::Job_Private *d_; 0190 0191 protected: 0192 Private::Job_Private *d(); 0193 const Private::Job_Private *d() const; 0194 0195 friend class Executor; 0196 /** The method that actually performs the job. 0197 * 0198 * It is called from execute(). This method is the one to overload it with the job's task. 0199 * 0200 * The Job will be executed in the specified thread. thread may be zero, indicating that the job is being executed some 0201 * other way (for example, synchronously by some other job). self specifies the job as the queue sees it. Whenever publishing 0202 * information about the job to the outside world, for example by emitting signals, use self, not this. self is the reference 0203 * counted object handled by the queue. Using it as signal parameters will amongst other things prevent thejob from being 0204 * memory managed and deleted. 0205 */ 0206 virtual void run(JobPointer self, Thread *thread) override = 0; 0207 0208 /** @brief Perform standard tasks before starting the execution of a job. 0209 * 0210 * The default implementation is empty. 0211 * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are 0212 * decorated expose the decorator's address, not the address of the decorated object. */ 0213 void defaultBegin(const JobPointer &job, Thread *thread) override; 0214 0215 /** @brief Perform standard task after the execution of a job. 0216 * 0217 * The default implementation is empty. 0218 * job is the Job that the queue is executing. It is not necessarily equal to this. For example, Jobs that are 0219 * decorated expose the decorator's address, not the address of the decorated object. */ 0220 void defaultEnd(const JobPointer &job, Thread *thread) override; 0221 }; 0222 0223 } 0224 0225 #endif // THREADWEAVER_JOB_H