QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
251  void taskCompleted();
252 
260  void taskTerminated();
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 
569  void allTasksFinished();
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
QgsWeakMapLayerPointerList
QList< QgsWeakMapLayerPointer > QgsWeakMapLayerPointerList
A list of weak pointers to QgsMapLayers.
Definition: qgsmaplayer.h:2153
QgsTaskManager::TaskDefinition::dependentTasks
QgsTaskList dependentTasks
List of dependent tasks which must be completed before task can run.
Definition: qgstaskmanager.h:429
QgsTask::SubTaskDependency
SubTaskDependency
Controls how subtasks relate to their parent task.
Definition: qgstaskmanager.h:167
QgsTask::Complete
@ Complete
Task successfully completed.
Definition: qgstaskmanager.h:66
QgsTask::description
QString description() const
Returns the task's description.
Definition: qgstaskmanager.h:122
QgsTask::Running
@ Running
Task is currently running.
Definition: qgstaskmanager.h:65
QgsTask::finished
virtual void finished(bool result)
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
Definition: qgstaskmanager.h:284
QgsTask::Queued
@ Queued
Task is queued and has not begun.
Definition: qgstaskmanager.h:63
QgsTaskManager::TaskDefinition
Definition of a task for inclusion in the manager.
Definition: qgstaskmanager.h:409
QgsTaskManager::TaskDefinition::TaskDefinition
TaskDefinition(QgsTask *task, const QgsTaskList &dependentTasks=QgsTaskList())
Constructor for TaskDefinition.
Definition: qgstaskmanager.h:416
QgsTask::status
TaskStatus status() const
Returns the current task status.
Definition: qgstaskmanager.h:117
SIP_SKIP
#define SIP_SKIP
Definition: qgis_sip.h:126
QgsTask::canCancel
bool canCancel() const
Returns true if the task can be canceled.
Definition: qgstaskmanager.h:106
QgsTask::TaskStatus
TaskStatus
Status of tasks.
Definition: qgstaskmanager.h:61
qgsmaplayer.h
QgsTaskManager
Task manager for managing a set of long-running QgsTask tasks. This class can be created directly,...
Definition: qgstaskmanager.h:392
qgis_sip.h
SIP_TRANSFER
#define SIP_TRANSFER
Definition: qgis_sip.h:36
Q_DECLARE_OPERATORS_FOR_FLAGS
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.
QgsTask::ParentDependsOnSubTask
@ ParentDependsOnSubTask
Subtask must complete before parent can begin.
Definition: qgstaskmanager.h:170
QgsTask::isActive
bool isActive() const
Returns true if the task is active, ie it is not complete and has not been canceled.
Definition: qgstaskmanager.h:112
QgsTaskList
QList< QgsTask * > QgsTaskList
List of QgsTask objects.
Definition: qgstaskmanager.h:33
QgsTask::Terminated
@ Terminated
Task was terminated or errored.
Definition: qgstaskmanager.h:67
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsTask::flags
Flags flags() const
Returns the flags associated with the task.
Definition: qgstaskmanager.h:94
QgsTask::OnHold
@ OnHold
Task is queued but on hold and will not be started.
Definition: qgstaskmanager.h:64
SIP_TRANSFERTHIS
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:53
QgsTask::Flag
Flag
Task flags.
Definition: qgstaskmanager.h:72
QgsTask::progress
double progress() const
Returns the task's progress (between 0.0 and 100.0)
Definition: qgstaskmanager.h:127
QgsTask
Abstract base class for long running background tasks. Tasks can be controlled directly,...
Definition: qgstaskmanager.h:54