QGIS API Documentation  3.27.0-Master (0e23467727)
qgstaskmanager.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgstaskmanager.h
3  ----------------
4  begin : April 2016
5  copyright : (C) 2016 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef QGSTASKMANAGER_H
19 #define QGSTASKMANAGER_H
20 
21 #include <QObject>
22 #include "qgis_sip.h"
23 #include <QMap>
24 #include <QFuture>
25 #include <QReadWriteLock>
26 #include <QSemaphore>
27 #include <QElapsedTimer>
28 
29 #include "qgis_core.h"
30 #include "qgsmaplayer.h"
31 
32 class QgsTask;
33 class QgsTaskRunnableWrapper;
34 
36 typedef QList< QgsTask * > QgsTaskList;
37 
54 class CORE_EXPORT QgsTask : public QObject
55 {
56  Q_OBJECT
57 
58  public:
59 
62  {
68  };
69  Q_ENUM( TaskStatus )
70 
71 
72  enum Flag
73  {
74  CanCancel = 1 << 1,
75  CancelWithoutPrompt = 1 << 2,
76  Hidden = 1 << 3,
77  Silent = 1 << 4,
78  AllFlags = CanCancel,
79  };
80  Q_DECLARE_FLAGS( Flags, Flag )
81 
82 
87  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
88 
89  ~QgsTask() override;
90 
94  Flags flags() const { return mFlags; }
95 
101  void setDescription( const QString &description );
102 
106  bool canCancel() const { return mFlags & CanCancel; }
107 
112  bool isActive() const { return mOverallStatus == Running; }
113 
117  TaskStatus status() const { return mOverallStatus; }
118 
122  QString description() const { return mDescription; }
123 
127  double progress() const { return mTotalProgress; }
128 
136  qint64 elapsedTime() const;
137 
147  virtual void cancel();
148 
156  void hold();
157 
164  void unhold();
165 
168  {
169  SubTaskIndependent = 0,
171  };
172 
193  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
194  SubTaskDependency subTaskDependency = SubTaskIndependent );
195 
201  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
202 
208  QList< QgsMapLayer * > dependentLayers() const;
209 
219  bool waitForFinished( int timeout = 30000 );
220 
221  signals:
222 
229  void progressChanged( double progress );
230 
237  void statusChanged( int status );
238 
244  void begun();
245 
252 
261 
262  protected:
263 
272  virtual bool run() = 0;
273 
284  virtual void finished( bool result ) { Q_UNUSED( result ) }
285 
291  bool isCanceled() const;
292 
293  protected slots:
294 
300  void setProgress( double progress );
301 
302  private slots:
303  void subTaskStatusChanged( int status );
304 
305  private:
306 
307  Flags mFlags;
308  QString mDescription;
310  TaskStatus mStatus = Queued;
312  TaskStatus mOverallStatus = Queued;
313 
318  QMutex mNotFinishedMutex;
319 
324  QSemaphore mNotStartedMutex;
325 
327  double mProgress = 0.0;
329  double mTotalProgress = 0.0;
330  bool mShouldTerminate = false;
331  mutable QMutex mShouldTerminateMutex;
332  int mStartCount = 0;
333 
334  struct SubTask
335  {
336  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
337  : task( task )
338  , dependencies( dependencies )
339  , dependency( dependency )
340  {}
341  QgsTask *task = nullptr;
342  QgsTaskList dependencies;
343  SubTaskDependency dependency;
344  };
345  QList< SubTask > mSubTasks;
346 
347  QgsWeakMapLayerPointerList mDependentLayers;
348 
349  QElapsedTimer mElapsedTime;
350 
351 
355  void start();
356 
360  void completed();
361 
365  void terminated();
366 
367 
368  void processSubTasksForHold();
369 
370  friend class QgsTaskManager;
371  friend class QgsTaskRunnableWrapper;
372  friend class TestQgsTaskManager;
373 
374  private slots:
375 
376  void processSubTasksForCompletion();
377 
378  void processSubTasksForTermination();
379 
380 };
381 
382 
383 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
384 
385 
392 class CORE_EXPORT QgsTaskManager : public QObject
393 {
394  Q_OBJECT
395 
396  public:
397 
402  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
403 
404  ~QgsTaskManager() override;
405 
410  {
411 
416  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
417  : task( task )
418  , dependentTasks( dependentTasks )
419  {}
420 
422  QgsTask *task = nullptr;
423 
430 
431  };
432 
441  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
442 
451  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
452 
458  QgsTask *task( long id ) const;
459 
463  QList<QgsTask *> tasks() const;
464 
466  int count() const;
467 
473  long taskId( QgsTask *task ) const;
474 
480  void cancelAll();
481 
483  bool dependenciesSatisfied( long taskId ) const;
484 
489  QSet< long > dependencies( long taskId ) const SIP_SKIP;
490 
498  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
499 
504  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
505 
510  QList< QgsTask * > activeTasks() const;
511 
520  int countActiveTasks( bool includeHidden = true ) const;
521 
522  public slots:
523 
528  void triggerTask( QgsTask *task );
529 
530  signals:
531 
537  void progressChanged( long taskId, double progress );
538 
544  void finalTaskProgressChanged( double progress );
545 
551  void statusChanged( long taskId, int status );
552 
557  void taskAdded( long taskId );
558 
563  void taskAboutToBeDeleted( long taskId );
564 
570 
575  void countActiveTasksChanged( int count );
576 
583  void taskTriggered( QgsTask *task );
584 
585  private slots:
586 
587  void taskProgressChanged( double progress );
588  void taskStatusChanged( int status );
589  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
590 
591  private:
592 
593  struct TaskInfo
594  {
595  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
596  void createRunnable();
597  QgsTask *task = nullptr;
598  QAtomicInt added;
599  int priority;
600  QgsTaskRunnableWrapper *runnable = nullptr;
601  };
602 
603  bool mInitialized = false;
604 
605 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
606  mutable QMutex *mTaskMutex;
607 #else
608  mutable QRecursiveMutex *mTaskMutex;
609 #endif
610 
611  QMap< long, TaskInfo > mTasks;
612  QMap< long, QgsTaskList > mTaskDependencies;
613  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
614 
616  long mNextTaskId = 1;
617 
619  QSet< QgsTask * > mActiveTasks;
621  QSet< QgsTask * > mParentTasks;
623  QSet< QgsTask * > mSubTasks;
624 
625  QSet< QgsTask * > mPendingDeletion;
626 
627  long addTaskPrivate( QgsTask *task,
628  QgsTaskList dependencies,
629  bool isSubTask,
630  int priority );
631 
632  bool cleanupAndDeleteTask( QgsTask *task );
633 
638  void processQueue();
639 
645  void cancelDependentTasks( long taskId );
646 
647  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
648 
650  bool hasCircularDependencies( long taskId ) const;
651 
652  friend class TestQgsTaskManager;
653 };
654 
655 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:73
Task manager for managing a set of long-running QgsTask tasks.
void finalTaskProgressChanged(double progress)
Will be emitted when only a single task remains to complete and that task has reported a progress cha...
void statusChanged(long taskId, int status)
Will be emitted when a task reports a status change.
void taskAdded(long taskId)
Emitted when a new task has been added to the manager.
void taskAboutToBeDeleted(long taskId)
Emitted when a task is about to be deleted.
void allTasksFinished()
Emitted when all tasks are complete.
void progressChanged(long taskId, double progress)
Will be emitted when a task reports a progress change.
void countActiveTasksChanged(int count)
Emitted when the number of active tasks changes.
void taskTriggered(QgsTask *task)
Emitted when a task is triggered.
Abstract base class for long running background tasks.
TaskStatus status() const
Returns the current task status.
Flags flags() const
Returns the flags associated with the task.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
double progress() const
Returns the task's progress (between 0.0 and 100.0)
virtual void finished(bool result)
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
virtual bool run()=0
Performs the task's operation.
void progressChanged(double progress)
Will be emitted by task when its progress changes.
void begun()
Will be emitted by task to indicate its commencement.
bool isActive() const
Returns true if the task is active, ie it is not complete and has not been canceled.
Flag
Task flags.
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e....
void statusChanged(int status)
Will be emitted by task when its status changes.
TaskStatus
Status of tasks.
@ Terminated
Task was terminated or errored.
@ Queued
Task is queued and has not begun.
@ OnHold
Task is queued but on hold and will not be started.
@ Running
Task is currently running.
@ Complete
Task successfully completed.
QString description() const
Returns the task's description.
SubTaskDependency
Controls how subtasks relate to their parent task.
@ ParentDependsOnSubTask
Subtask must complete before parent can begin.
bool canCancel() const
Returns true if the task can be canceled.
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:53
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_TRANSFER
Definition: qgis_sip.h:36
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsField::ConfigurationFlags) CORE_EXPORT QDataStream &operator<<(QDataStream &out
Writes the field to stream out. QGIS version compatibility is not guaranteed.
QList< QgsWeakMapLayerPointer > QgsWeakMapLayerPointerList
A list of weak pointers to QgsMapLayers.
Definition: qgsmaplayer.h:2153
QList< QgsTask * > QgsTaskList
List of QgsTask objects.
Definition of a task for inclusion in the manager.
TaskDefinition(QgsTask *task, const QgsTaskList &dependentTasks=QgsTaskList())
Constructor for TaskDefinition.
QgsTaskList dependentTasks
List of dependent tasks which must be completed before task can run.